Repository: qiniu/py
Branch: master
Commit: 448d79fd9516
Files: 37
Total size: 80.7 KB
Directory structure:
gitextract_iqe7pocv/
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── class.go
├── code.go
├── code_test.go
├── dict.go
├── error.go
├── examples/
│ └── gomodule/
│ └── gomodule.go
├── exc.go
├── exception.go
├── float.go
├── goargs.go
├── gofunction.c
├── gofunction.go
├── gofunction.h
├── gomodule.go
├── gomodule_test.go
├── goregister.go
├── goregister_test.go
├── int.go
├── long.go
├── module.go
├── module_test.go
├── none.go
├── number.go
├── object.go
├── object_test.go
├── python.go
├── pyutil/
│ ├── call.go
│ ├── call_test.go
│ ├── var.go
│ └── var_test.go
├── string.go
├── tuple.go
└── type.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
*.pyc
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
================================================
FILE: CHANGELOG.md
================================================
#CHANGELOG
## v1.1.00
2013-05-28 Issue [#17](https://github.com/qiniu/py/pull/17):
- bugfix: Closure add methodDef to fix that gc recycle methodDef
- 支持 Float 类型
## v1.0.01
2013-03-10 Issue [#5](https://github.com/qiniu/py/pull/5):
- 增加 gomodule 样例
- Travis-CI 支持
================================================
FILE: LICENSE
================================================
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
py - Golang bindings to the CPython C-API
==
**NOTE**: This project is **unmaintained**. Maybe [https://github.com/go-python/cpy3](https://github.com/go-python/cpy3) is a good replacement.
py is Golang bindings to the CPython C-API.
py project's homepage is: https://github.com/qiniu/py
# Install
```
go get github.com/qiniu/py
```
# Example
```{go}
package main
import (
"fmt"
"github.com/qiniu/log"
"github.com/qiniu/py"
)
// -------------------------------------------------------------------
type FooModule struct {
}
func (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s string
err = py.Parse(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar:", i, s)
return py.IncNone(), nil
}
func (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s []string
err = py.ParseV(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar2:", i, s)
return py.IncNone(), nil
}
// -------------------------------------------------------------------
const pyCode = `
import foo
foo.bar(1, 'Hello')
foo.bar2(1, 'Hello', 'world!')
`
func main() {
gomod, err := py.NewGoModule("foo", "", new(FooModule))
if err != nil {
log.Fatal("NewGoModule failed:", err)
}
defer gomod.Decref()
code, err := py.Compile(pyCode, "", py.FileInput)
if err != nil {
log.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := py.ExecCodeModule("test", code.Obj())
if err != nil {
log.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
}
// -------------------------------------------------------------------
```
================================================
FILE: class.go
================================================
package py
// #include <Python.h>
// static inline int classCheck(PyObject *o) { return PyClass_Check(o); }
import "C"
import "unsafe"
type Class struct {
Base
o C.PyClassObject
}
// ClassType is the Type object that represents the Class type.
var ClassType = (*Type)(unsafe.Pointer(&C.PyClass_Type))
func newClass(obj *C.PyObject) *Class {
return (*Class)(unsafe.Pointer(obj))
}
func AsClass(o *Base) (v *Class, ok bool) {
if ok = C.classCheck(o.c()) != 0; ok {
v = newClass(o.c())
}
return
}
func (t *Class) NewNoArgs() (ret *Base, err error) {
args := NewTuple(0)
defer args.Decref()
return t.New(args, nil)
}
// Return value: New reference.
// Create a new instance of a specific class. The parameters arg and kw are used as
// the positional and keyword parameters to the object’s constructor.
func (t *Class) New(args *Tuple, kw *Dict) (ret *Base, err error) {
ret1 := C.PyInstance_New(t.c(), args.c(), kw.c())
return obj2ObjErr(ret1)
}
func (t *Class) NewObjArgs(args ...*Base) (ret *Base, err error) {
args1 := PackTuple(args...)
defer args1.Decref()
return t.New(args1, nil)
}
// Return true if klass is a subclass of base. Return false in all other cases.
func (t *Class) IsSubclass(base *Base) bool {
return C.PyClass_IsSubclass(t.c(), base.c()) != 0
}
================================================
FILE: code.go
================================================
package py
/*
#include <Python.h>
static inline int codeCheck(PyObject *o) { return PyCode_Check(o); }
static inline void decref(PyObject *obj) { Py_DECREF(obj); }
static inline FILE* openFile(char* name) {
return fopen(name, "r");
}
static inline PyObject* compileString(char* text, char* filename, int start) {
return Py_CompileString(text, filename, start);
}
static PyObject* compileFile(FILE* f, char* name, int start) {
struct _node *n = PyParser_SimpleParseFile(f, name, start);
if (!n) return NULL;
return (PyObject*)PyNode_Compile(n, name);
}
*/
import "C"
import "unsafe"
// ------------------------------------------------------------------------------------------
// type StartToken
type StartToken int
const (
EvalInput = StartToken(C.Py_eval_input) // for isolated expressions
FileInput = StartToken(C.Py_file_input) // for sequences of statements as read from a file or other source;
// to use when compiling arbitrarily long Python source code.
SingleInput = StartToken(C.Py_single_input) // for a single statement; used for the interactive interpreter loop.
)
// ------------------------------------------------------------------------------------------
// type Code
type Code struct {
Base
o C.PyCodeObject
}
// CodeType is the Type object that represents the Code type.
var CodeType = (*Type)(unsafe.Pointer(&C.PyCode_Type))
func newCode(obj *C.PyObject) *Code {
return (*Code)(unsafe.Pointer(obj))
}
func AsCode(o *Base) (v *Code, ok bool) {
if ok = C.codeCheck(o.c()) != 0; ok {
v = newCode(o.c())
}
return
}
func Compile(text, filename string, start StartToken) (*Code, error) {
t := C.CString(text)
defer C.free(unsafe.Pointer(t))
fn := C.CString(filename)
defer C.free(unsafe.Pointer(fn))
ret := C.compileString(t, fn, C.int(start))
if ret == nil {
return nil, exception()
}
return newCode(ret), nil
}
func CompileFile(name string, start StartToken) (*Code, error) {
fn := C.CString(name)
defer C.free(unsafe.Pointer(fn))
file, err := C.openFile(fn)
if file == nil {
return nil, err
}
defer C.fclose(file)
ret := C.compileFile(file, fn, C.int(start))
if ret == nil {
return nil, exception()
}
return newCode(ret), nil
}
// Return value: New reference.
func (code *Code) Eval(globals, locals *Base) (*Base, error) {
pyCode := (*C.PyCodeObject)(unsafe.Pointer(code))
ret := C.PyEval_EvalCode(pyCode, globals.c(), locals.c())
return obj2ObjErr(ret)
}
func (code *Code) Run(globals, locals *Base) error {
pyCode := (*C.PyCodeObject)(unsafe.Pointer(code))
ret := C.PyEval_EvalCode(pyCode, globals.c(), locals.c())
if ret == nil {
return exception()
}
C.decref(ret)
return nil
}
// ------------------------------------------------------------------------------------------
func Run(text string) error {
t := C.CString(text)
defer C.free(unsafe.Pointer(t))
ret := C.PyRun_SimpleStringFlags(t, nil)
return int2Err(ret)
}
// Return a dictionary of the builtins in the current execution frame, or the interpreter of
// the thread state if no frame is currently executing.
//
// Return value: Borrowed reference.
func GetBuiltins() *Base {
ret := C.PyEval_GetBuiltins()
return newObject(ret)
}
// Return a dictionary of the global variables in the current execution frame,
// or NULL if no frame is currently executing.
//
// Return value: Borrowed reference
func GetLocals() *Base {
ret := C.PyEval_GetLocals()
return newObject(ret)
}
// Return a dictionary of the local variables in the current execution frame,
// or NULL if no frame is currently executing.
//
// Return value: Borrowed reference
func GetGlobals() *Base {
ret := C.PyEval_GetGlobals()
return newObject(ret)
}
// ------------------------------------------------------------------------------------------
================================================
FILE: code_test.go
================================================
package py
import (
"testing"
)
type compileCase struct {
exp string
ret string
start StartToken
}
var g_compileCases = []compileCase{
{"1+2", "3", EvalInput},
{"1+2", "None", SingleInput}, // echo
{"1+2", "None", FileInput},
}
func TestCompile(t *testing.T) {
for _, c := range g_compileCases {
code, err := Compile(c.exp, "", c.start)
if err != nil {
t.Fatal("Compile failed:", err)
}
defer code.Decref()
globals := NewDict()
defer globals.Decref()
locals := NewDict()
defer locals.Decref()
ret, err := code.Eval(globals.Obj(), locals.Obj())
if err != nil {
t.Fatal("Eval failed:", err)
}
defer ret.Decref()
if ret.String() != c.ret {
t.Fatal("Eval ret:", ret.String())
}
}
}
type evalLocalGlobalsCase struct {
exp string
globals string
locals string
start StartToken
}
var g_evalLocalGlobalsCases = []evalLocalGlobalsCase{
{"v=1+2", "{}", "{'v': 3}", FileInput},
{"v=1+2", "{}", "{'v': 3}", SingleInput}, // echo
// {"v=1+2", "{}", "{'v': 3}", EvalInput}, // compile error
}
func _TestEvalLocalGlobals(t *testing.T) {
Initialize()
defer Finalize()
for _, c := range g_evalLocalGlobalsCases {
code, err := Compile(c.exp, "", c.start)
if err != nil {
t.Fatal("Compile failed:", c.exp, c.start, err)
}
defer code.Decref()
globals := NewDict()
defer globals.Decref()
locals := NewDict()
defer locals.Decref()
err = code.Run(globals.Obj(), locals.Obj())
if err != nil {
t.Fatal("Run failed:", err)
}
println(globals.String(), locals.String())
if locals.String() != c.locals || globals.String() != c.globals {
t.Fatal("Run:", globals.String(), locals.String())
}
}
}
================================================
FILE: dict.go
================================================
package py
// #include <Python.h>
// static inline int dictCheck(PyObject *o) { return PyDict_Check(o); }
// static inline int dictCheckE(PyObject *o) { return PyDict_CheckExact(o); }
import "C"
import "unsafe"
// *Dict represents a Python dictionary. In addition to satisfying the Object
// interface, Dict pointers also have a number of methods defined - representing
// the PyDict_XXX functions from the Python C API.
type Dict struct {
Base
o C.PyDictObject
}
// DictType is the Type object that represents the Dict type.
var DictType = (*Type)(unsafe.Pointer(&C.PyDict_Type))
func newDict(obj *C.PyObject) *Dict {
return (*Dict)(unsafe.Pointer(obj))
}
// NewDict creates a new empty dictionary.
//
// Return value: New Reference.
func NewDict() *Dict {
ret := C.PyDict_New()
return newDict(ret)
}
func NewDictProxy(obj *Base) *Dict {
ret := C.PyDictProxy_New(obj.c())
return newDict(ret)
}
func AsDict(o *Base) (v *Dict, ok bool) {
if ok = C.dictCheck(o.c()) != 0; ok {
v = newDict(o.c())
}
return
}
// CheckExact returns true if d is an actual dictionary object, and not an
// instance of a sub type.
func (d *Dict) CheckExact() bool {
ret := C.dictCheckE(d.c())
if int(ret) != 0 {
return true
}
return false
}
// Clear empties the dictionary d of all key-value pairs.
func (d *Dict) Clear() {
C.PyDict_Clear(d.c())
}
// Contains Returns true if the dictionary contains the given key. This is
// equivalent to the Python expression "key in d".
func (d *Dict) Contains(key *Base) (bool, error) {
ret := C.PyDict_Contains(d.c(), key.c())
return int2BoolErr(ret)
}
// Copy returns a new dictionary that contains the same key-values pairs as d.
//
// Return value: New Reference.
func (d *Dict) Copy() (*Base, error) {
ret := C.PyDict_Copy(d.c())
return obj2ObjErr(ret)
}
// SetItem inserts "val" into dictionary d with the key "key". If "key" is not
// hashable, then a TypeError will be returned.
func (d *Dict) SetItem(key, val *Base) error {
ret := C.PyDict_SetItem(d.c(), key.c(), val.c())
return int2Err(ret)
}
// SetItemString inserts "val" into dictionary d with the key "key" (or rather,
// with a *String with the value of "key" will be used as the key). If "key" is
// not hashable, then a TypeError will be returned.
func (d *Dict) SetItemString(key string, val *Base) error {
s := C.CString(key)
defer C.free(unsafe.Pointer(s))
ret := C.PyDict_SetItemString(d.c(), s, val.c())
return int2Err(ret)
}
// DelItem removes the entry with the key of "key" from the dictionary d. If
// "key" is not hashable, a TypeError is returned.
func (d *Dict) DelItem(key *Base) error {
ret := C.PyDict_DelItem(d.c(), key.c())
return int2Err(ret)
}
// DelItem removes the entry with the key of "key" (or rather, with a *String
// with the value of "key" as the key) from the dictionary d.
func (d *Dict) DelItemString(key string) error {
s := C.CString(key)
defer C.free(unsafe.Pointer(s))
ret := C.PyDict_DelItemString(d.c(), s)
return int2Err(ret)
}
// GetItem returns the Object from dictionary d which has the key "key". If
// there is no such Object, then nil is returned (without an error).
//
// Return value: Borrowed Reference.
func (d *Dict) GetItem(key *Base) *Base {
ret := C.PyDict_GetItem(d.c(), key.c())
return newObject(ret)
}
// GetItemString returns the Object from dictionary d which has the key "key"
// (or rather, which has a *String with the value of "key" as the key). If
// there is no such Object, then nil is returned (without an error).
//
// Return value: Borrowed Reference.
func (d *Dict) GetItemString(key string) *Base {
s := C.CString(key)
defer C.free(unsafe.Pointer(s))
ret := C.PyDict_GetItemString(d.c(), s)
return newObject(ret)
}
/*
// Items returns a *List containing all the items from the dictionary d, as with
// the Python "d.items()".
//
// Return value: New Reference.
func (d *Dict) Items() (*List, error) {
ret := C.PyDict_Items(d.c())
return newList(ret), exception()
}
// Keys returns a *List containing all the keys from the dictionary d, as with
// the Python "d.keys()".
//
// Return value: New Reference.
func (d *Dict) Keys() (*List, error) {
ret := C.PyDict_Keys(d.c())
return newList(ret), exception()
}
// Values returns a *List containing all the values from the dictionary d, as
// with the Python "d.values()".
//
// Return value: New Reference.
func (d *Dict) Values() (*List, error) {
ret := C.PyDict_Values(d.c())
return newList(ret), exception()
}
*/
// Size returns the number of items in the dictionary d. This is equivalent to
// the Python "len(d)".
func (d *Dict) Size() int {
ret := C.PyDict_Size(d.c())
if ret < 0 {
panic(exception())
}
return int(ret)
}
// PyDict_Next
// Merge merges key values pairs from Object o (which may be a dictionary, or an
// object that supports "o.keys()" and "o[key]") into the dictionary d. If
// override is true then a matching key in d will have it's value replaced by
// the one in o, else the value in d will be left.
func (d *Dict) Merge(o *Base, override bool) error {
over := 0
if override {
over = 1
}
ret := C.PyDict_Merge(d.c(), o.c(), C.int(over))
return int2Err(ret)
}
// Update replaces key values pairs in d with those from o. It is equivalent to
// d.Merge(o, true) in Go, or "d.update(o)" in Python.
func (d *Dict) Update(o *Base) error {
ret := C.PyDict_Update(d.c(), o.c())
return int2Err(ret)
}
// MergeFromSeq2 merges key values pairs from the Object o (which must be an
// iterable object, where each item is an iterable of length 2 - the key value
// pairs). If override is true then the last key value pair with the same key
// wins, otherwise the first instance does (where an instance already in d
// counts before any in o).
func (d *Dict) MergeFromSeq2(o *Base, override bool) error {
over := 0
if override {
over = 1
}
ret := C.PyDict_MergeFromSeq2(d.c(), o.c(), C.int(over))
return int2Err(ret)
}
// Map returns a Go map that contains the values from the Python dictionary,
// indexed by the keys. The keys and values are the same as in the Python
// dictionary, but changes to the Go map are not propogated back to the Python
// dictionary.
//
// Note: the map holds borrowed references
func (d *Dict) Map() map[*Base]*Base {
m := make(map[*Base]*Base, d.Size())
var p C.Py_ssize_t
var k *C.PyObject
var v *C.PyObject
for int(C.PyDict_Next(d.c(), &p, &k, &v)) != 0 {
key := newObject(k)
value := newObject(v)
m[key] = value
}
return m
}
// MapString is similar to Map, except that the keys are first converted to
// strings. If the keys are not all Python strings, then an error is returned.
//
// Note: the map holds borrowed references
func (d *Dict) MapString() (map[string]*Base, error) {
m := make(map[string]*Base, d.Size())
var p DictIter
var k, v *Base
for d.Next(&p, &k, &v) {
s, ok := AsString(k)
if !ok {
return nil, TypeError.Err("%v is not a string", k)
}
m[s.String()] = v
}
return m, nil
}
type DictIter C.Py_ssize_t
// Iterate over all key-value pairs in the dictionary d.
// The Py_ssize_t referred to by ppos must be initialized to 0 prior to the first call to this function
// to start the iteration; the function returns true for each pair in the dictionary, and false once all
// pairs have been reported. The parameters pkey and pvalue should either point to PyObject* variables
// that will be filled in with each key and value, respectively, or may be NULL. Any references returned
// through them are borrowed. ppos should not be altered during iteration. Its value represents offsets
// within the internal dictionary structure, and since the structure is sparse, the offsets are not consecutive.
func (d *Dict) Next(pos *DictIter, k, v **Base) bool {
k1 := (**C.PyObject)(unsafe.Pointer(k))
v1 := (**C.PyObject)(unsafe.Pointer(v))
return C.PyDict_Next(d.c(), (*C.Py_ssize_t)(pos), k1, v1) != 0
}
================================================
FILE: error.go
================================================
package py
// #include <Python.h>
// static inline void incref(PyObject *obj) { Py_INCREF(obj); }
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
// static inline void xdecref(PyObject *obj) { Py_XDECREF(obj); }
import "C"
import "fmt"
import "syscall"
import "strings"
import "runtime"
import "github.com/qiniu/errors"
// Error represents a Python exception as a Go struct that implements the
// error interface. It allows Go code to handle Python exceptions in an
// idiomatic Go fashion.
type Error struct {
Kind *Base
Value *Base
tb *C.PyObject
}
func newError(kind, val *Base, tb *C.PyObject) *Error {
e := &Error{kind, val, tb}
runtime.SetFinalizer(e, (*Error).release)
return e
}
func (e *Error) release() error {
if e.Kind != nil {
e.Kind.Decref()
e.Value.Decref()
e.Kind = nil
e.Value = nil
if e.tb != nil {
C.decref(e.tb)
e.tb = nil
}
}
return nil
}
// Error() returns a string representation of the Python exception represented
// by the Error e. This is the same as the final line of the Python output from
// an uncaught exception.
func (e *Error) Error() string {
kind := e.Kind.String()
if strings.HasPrefix(kind, "<type 'exceptions.") {
kind = kind[18:len(kind)-2]
}
return kind + ": " + e.Value.String()
}
/*
// Matches returns true if e.Kind matches the exception in exc. If exc is a
// Class, then true is returned if e.Kind is an instance. If exc is a Tuple,
// then all elements (and recursively for sub elements) are searched for a
// match.
func (e *Error) Matches(exc Object) bool {
return C.PyErr_GivenExceptionMatches(c(e.Kind), c(exc)) != 0
}
*/
// Normalize adjusts e.Kind/e.Value in the case that the values aren't
// normalized to start with. It's possible that an Error returned from Python
// might have e.Kind be a Class, with e.Value not being an instance of that
// class, Normalize will fix this. The separate normalization is implemented in
// Python to improve performance.
func (e *Error) Normalize() {
exc := e.Kind.c()
val := e.Value.c()
tb := e.tb
C.PyErr_NormalizeException(&exc, &val, &tb)
e.Kind = newObject(exc)
e.Value = newObject(val)
e.tb = tb
}
// NewErrorV returns a new Error of the specified kind, and with the given
// value.
func NewErrorV(kind *Base, value *Base) *Error {
kind.Incref()
value.Incref()
return newError(kind, value, nil)
}
// NewError returns a new Error of the specified kind, and with the value
// being a new String containing the string created the given format and args.
func NewError(kind *Base, format string, args ...interface{}) *Error {
msg := fmt.Sprintf(format, args...)
kind.Incref()
val := NewString(msg)
return newError(kind, &val.Base, nil)
}
func Raise(err error) {
var val *C.PyObject
var exc = C.PyExc_Exception
e, ok := err.(*Error)
if ok {
exc = e.Kind.c()
val = e.Value.c()
} else {
v := NewString(errors.Detail(err))
val = v.c()
defer C.decref(val)
}
C.PyErr_SetObject(exc, val)
}
func GetException() error {
return exception()
}
func exceptionRaised() bool {
return C.PyErr_Occurred() != nil
}
func exception() error {
if C.PyErr_Occurred() == nil {
return syscall.EFAULT
}
var t, v, tb *C.PyObject
C.PyErr_Fetch(&t, &v, &tb)
return newError(newObject(t), newObject(v), tb)
}
func ssize_t2Int64Err(s C.Py_ssize_t) (int64, error) {
if s < 0 {
return 0, exception()
}
return int64(s), nil
}
func int2BoolErr(i C.int) (bool, error) {
if i < 0 {
return false, exception()
}
return i > 0, nil
}
func int2Err(i C.int) error {
if i < 0 {
return exception()
}
return nil
}
func obj2ObjErr(obj *C.PyObject) (*Base, error) {
if obj == nil {
return nil, exception()
}
return newObject(obj), nil
}
================================================
FILE: examples/gomodule/gomodule.go
================================================
package main
import (
"fmt"
"github.com/qiniu/log"
"github.com/qiniu/py"
)
// -------------------------------------------------------------------
type FooModule struct {
}
func (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s string
err = py.Parse(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar:", i, s)
return py.IncNone(), nil
}
func (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s []string
err = py.ParseV(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar2:", i, s)
return py.IncNone(), nil
}
// -------------------------------------------------------------------
const pyCode = `
import foo
foo.bar(1, 'Hello')
foo.bar2(1, 'Hello', 'world!')
`
func main() {
gomod, err := py.NewGoModule("foo", "", new(FooModule))
if err != nil {
log.Fatal("NewGoModule failed:", err)
}
defer gomod.Decref()
code, err := py.Compile(pyCode, "", py.FileInput)
if err != nil {
log.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := py.ExecCodeModule("test", code.Obj())
if err != nil {
log.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
}
// -------------------------------------------------------------------
================================================
FILE: exc.go
================================================
package py
// #include <Python.h>
import "C"
var (
BaseException = newException(C.PyExc_BaseException)
Exception = newException(C.PyExc_Exception)
StopIteration = newException(C.PyExc_StopIteration)
GeneratorExit = newException(C.PyExc_GeneratorExit)
StandardError = newException(C.PyExc_StandardError)
ArithmeticError = newException(C.PyExc_ArithmeticError)
LookupError = newException(C.PyExc_LookupError)
AssertionError = newException(C.PyExc_AssertionError)
AttributeError = newException(C.PyExc_AttributeError)
EOFError = newException(C.PyExc_EOFError)
FloatingPointError = newException(C.PyExc_FloatingPointError)
EnvironmentError = newException(C.PyExc_EnvironmentError)
IOError = newException(C.PyExc_IOError)
OSError = newException(C.PyExc_OSError)
ImportError = newException(C.PyExc_ImportError)
IndexError = newException(C.PyExc_IndexError)
KeyError = newException(C.PyExc_KeyError)
KeyboardInterrupt = newException(C.PyExc_KeyboardInterrupt)
MemoryError = newException(C.PyExc_MemoryError)
NameError = newException(C.PyExc_NameError)
OverflowError = newException(C.PyExc_OverflowError)
RuntimeError = newException(C.PyExc_RuntimeError)
NotImplementedError = newException(C.PyExc_NotImplementedError)
SyntaxError = newException(C.PyExc_SyntaxError)
IndentationError = newException(C.PyExc_IndentationError)
TabError = newException(C.PyExc_TabError)
ReferenceError = newException(C.PyExc_ReferenceError)
SystemError = newException(C.PyExc_SystemError)
SystemExit = newException(C.PyExc_SystemExit)
TypeError = newException(C.PyExc_TypeError)
UnboundLocalError = newException(C.PyExc_UnboundLocalError)
UnicodeError = newException(C.PyExc_UnicodeError)
UnicodeEncodeError = newException(C.PyExc_UnicodeEncodeError)
UnicodeDecodeError = newException(C.PyExc_UnicodeDecodeError)
UnicodeTranslateError = newException(C.PyExc_UnicodeTranslateError)
ValueError = newException(C.PyExc_ValueError)
ZeroDivisionError = newException(C.PyExc_ZeroDivisionError)
BufferError = newException(C.PyExc_BufferError)
MemoryErrorInst = newException(C.PyExc_MemoryErrorInst)
RecursionErrorInst = newException(C.PyExc_RecursionErrorInst)
Warning = newException(C.PyExc_Warning)
UserWarning = newException(C.PyExc_UserWarning)
DeprecationWarning = newException(C.PyExc_DeprecationWarning)
PendingDeprecationWarning = newException(C.PyExc_PendingDeprecationWarning)
SyntaxWarning = newException(C.PyExc_SyntaxWarning)
RuntimeWarning = newException(C.PyExc_RuntimeWarning)
FutureWarning = newException(C.PyExc_FutureWarning)
ImportWarning = newException(C.PyExc_ImportWarning)
UnicodeWarning = newException(C.PyExc_UnicodeWarning)
BytesWarning = newException(C.PyExc_BytesWarning)
)
================================================
FILE: exception.go
================================================
package py
// #include <Python.h>
import "C"
import "unsafe"
type ExceptionClass struct {
Base
o C.PyBaseExceptionObject
}
func newException(obj *C.PyObject) *ExceptionClass {
return (*ExceptionClass)(unsafe.Pointer(obj))
}
// ErrV returns a new Error of the specified kind, and with the given value.
func (kind *ExceptionClass) ErrV(obj *Base) *Error {
return NewErrorV(&kind.Base, obj)
}
// Err returns a new Error of the specified kind, and with the value being a
// new String containing the string created the given format and args.
func (kind *ExceptionClass) Err(format string, args ...interface{}) *Error {
return NewError(&kind.Base, format, args...)
}
================================================
FILE: float.go
================================================
package py
// #include <Python.h>
// static inline double floatCheck(PyObject *o) { return PyFloat_Check(o); }
import "C"
import "unsafe"
type Float struct {
Base
NumberProtocol
o C.PyFloatObject
}
// FloatType is the Type object that represents the Float type.
var FloatType = (*Type)(unsafe.Pointer(&C.PyFloat_Type))
func newFloat(obj *C.PyObject) *Float {
return (*Float)(unsafe.Pointer(obj))
}
func NewFloat(i float64) *Float {
return newFloat(C.PyFloat_FromDouble(C.double(i)))
}
func AsFloat(o *Base) (v *Float, ok bool) {
if ok = C.floatCheck(o.c()) != 0; ok {
v = newFloat(o.c())
}
return
}
func NewFloatFromString(s string) *Float {
cs := NewString(s)
return newFloat(C.PyFloat_FromString((*C.PyObject)(unsafe.Pointer(cs.Obj())), nil))
}
func (f *Float) Float() float64 {
return float64(C.PyFloat_AsDouble(f.c()))
}
================================================
FILE: goargs.go
================================================
package py
import (
"reflect"
"syscall"
"github.com/qiniu/log"
"github.com/qiniu/errors"
)
// ------------------------------------------------------------------------------------------
func ToInt(in *Base) (int, bool) {
l, ok := ToLong(in)
return int(l), ok
}
func ToLong(in *Base) (int64, bool) {
if v, ok := AsInt(in); ok {
return int64(v.Int()), true
}
if v, ok := AsLong(in); ok {
return int64(v.Long()), true
}
return 0, false
}
func ToString(in *Base) (string, bool) {
if v, ok := AsString(in); ok {
return v.String(), true
}
return "", false
}
func ToInterface(in *Base) (v interface{}, ok bool) {
if v, ok = ToLong(in); ok {
return
} else if v, ok = ToString(in); ok {
return
}
return
}
// ------------------------------------------------------------------------------------------
func assignToMap(in *Base, out reflect.Value) (err error) {
dict, ok := AsDict(in)
if !ok {
err = errors.Info(syscall.EINVAL, "py.AssignTo", "uncompatible type")
return
}
mapTy := out.Type()
m := reflect.MakeMap(mapTy)
keyTy := mapTy.Key()
valTy := mapTy.Elem()
log.Debug("assignToMap:", mapTy, keyTy, valTy)
var iter DictIter
var k, v *Base
for dict.Next(&iter, &k, &v) {
kout := reflect.New(keyTy)
err = AssignTo(k, kout.Interface())
if err != nil {
err = errors.Info(err, "py.AssignTo", "assign map key").Detail(err)
return
}
vout := reflect.New(valTy)
err = AssignTo(v, vout.Interface())
if err != nil {
err = errors.Info(err, "py.AssignTo", "assign map val").Detail(err)
return
}
m.SetMapIndex(kout.Elem(), vout.Elem())
}
out.Set(m)
return nil
}
func assignToComplex(in *Base, out1 reflect.Value) (err error) {
if out1.Kind() != reflect.Ptr {
err = errors.Info(syscall.EINVAL, "py.AssignTo", "not assignable")
return
}
out := out1.Elem()
switch out.Kind() {
case reflect.Map:
return assignToMap(in, out)
default:
err = errors.Info(syscall.EINVAL, "py.AssignTo", "unsupported input type", reflect.TypeOf(out))
return
}
return
}
func AssignTo(in *Base, out interface{}) (err error) {
var ok bool
switch v := out.(type) {
case *string:
*v, ok = ToString(in)
case *int64:
*v, ok = ToLong(in)
case *int:
*v, ok = ToInt(in)
case *interface{}:
*v, ok = ToInterface(in)
return
default:
return assignToComplex(in, reflect.ValueOf(out))
}
if !ok {
err = errors.Info(syscall.EINVAL, "py.AssignTo", "can not convert type", reflect.TypeOf(out))
}
return
}
// ------------------------------------------------------------------------------------------
func Parse(in *Tuple, out ...interface{}) (err error) {
n := in.Size()
if n != len(out) {
err = errors.Info(syscall.EINVAL, "py.Parse", "invalid argument count")
return
}
for i := 0; i < n; i++ {
v2, err2 := in.GetItem(i)
if err2 != nil {
err = errors.Info(err2, "py.Parse", "invalid argument", i+1).Detail(err2)
return
}
err2 = AssignTo(v2, out[i])
if err2 != nil {
err = errors.Info(err2, "py.Parse", "assign argument failed", i+1).Detail(err2)
return
}
}
return
}
func ParseV(in *Tuple, out ...interface{}) (err error) {
n1 := in.Size()
n := len(out) - 1
if n1 < n || n < 0 {
err = errors.Info(syscall.EINVAL, "py.ParseV", "argument count is not enough")
return
}
slicePtr := reflect.TypeOf(out[n])
if slicePtr.Kind() != reflect.Ptr {
err = errors.Info(syscall.EINVAL, "py.ParseV", "last argument is not a slice pointer")
return
}
sliceTy := slicePtr.Elem()
if sliceTy.Kind() != reflect.Slice {
err = errors.Info(syscall.EINVAL, "py.ParseV", "last argument is not a slice pointer")
return
}
for i := 0; i < n; i++ {
v2, err2 := in.GetItem(i)
if err2 != nil {
err = errors.Info(err2, "py.ParseV", "invalid argument", i+1).Detail(err2)
return
}
err2 = AssignTo(v2, out[i])
if err2 != nil {
err = errors.Info(err2, "py.ParseV", "assign argument failed", i+1).Detail(err2)
return
}
}
slice := reflect.MakeSlice(sliceTy, n1-n, n1-n)
for i := n; i < n1; i++ {
v2, err2 := in.GetItem(i)
if err2 != nil {
err = errors.Info(err2, "py.ParseV", "invalid argument", i+1).Detail(err2)
return
}
err2 = AssignTo(v2, slice.Index(i-n).Addr().Interface())
if err2 != nil {
err = errors.Info(err2, "py.ParseV", "assign argument failed", i+1).Detail(err2)
return
}
}
reflect.ValueOf(out[n]).Elem().Set(slice)
return
}
// ------------------------------------------------------------------------------------------
================================================
FILE: gofunction.c
================================================
#include <Python.h>
#include "_cgo_export.h"
int setMethod(PyMethodDef* d, int nin) {
switch (nin) {
case 3:
d->ml_meth = (PyCFunction)goClassCallMethodKwds;
d->ml_flags = METH_VARARGS | METH_KEYWORDS;
break;
case 2:
d->ml_meth = (PyCFunction)goClassCallMethodArgs;
d->ml_flags = METH_VARARGS;
break;
default:
return -1;
}
return 0;
}
================================================
FILE: gofunction.go
================================================
package py
/*
#include <Python.h>
#include "gofunction.h"
static inline void decref(PyObject *obj) { Py_DECREF(obj); }
*/
import "C"
import "unsafe"
import "reflect"
type Closure struct { // closure = self.method
Self reflect.Value
Method reflect.Value
methodDef C.PyMethodDef
}
func (closure *Closure) NewFunction(name string, nin int, doc string) *Base {
d := &closure.methodDef
d.ml_name = C.CString(name)
defer C.free(unsafe.Pointer(d.ml_name))
if C.setMethod(d, C.int(nin)) != 0 {
panic("Invalid arguments: nin")
}
if doc != "" {
d.ml_doc = C.CString(doc)
defer C.free(unsafe.Pointer(d.ml_doc))
}
ctx := uintptr(unsafe.Pointer(closure))
self := C.PyLong_FromLongLong(C.longlong(ctx))
defer C.decref(self)
f := C.PyCFunction_NewEx(d, self, nil)
return (*Base)(unsafe.Pointer(f))
}
//export goClassCallMethodArgs
func goClassCallMethodArgs(obj, args unsafe.Pointer) unsafe.Pointer {
// Unpack context and self pointer from obj
t := (*C.PyObject)(obj)
closure := (*Closure)(unsafe.Pointer(uintptr(C.PyLong_AsLongLong(t))))
// Get args ready to use, by turning it into a pointer of the appropriate
// type
a := (*Tuple)(args)
in := []reflect.Value{closure.Self, reflect.ValueOf(a)}
out := closure.Method.Call(in)
err := out[1].Interface()
if err != nil {
Raise(err.(error))
return nil
}
ret := out[0].Interface().(*Base)
return unsafe.Pointer(ret)
}
//export goClassCallMethodKwds
func goClassCallMethodKwds(obj, args, kwds unsafe.Pointer) unsafe.Pointer {
// Unpack context and self pointer from obj
t := (*C.PyObject)(obj)
closure := (*Closure)(unsafe.Pointer(uintptr(C.PyLong_AsLongLong(t))))
// Get args and kwds ready to use, by turning them into pointers of the
// appropriate type
a := (*Tuple)(args)
k := (*Dict)(kwds)
in := []reflect.Value{closure.Self, reflect.ValueOf(a), reflect.ValueOf(k)}
out := closure.Method.Call(in)
err := out[1].Interface()
if err != nil {
Raise(err.(error))
return nil
}
ret := out[0].Interface().(*Base)
return unsafe.Pointer(ret)
}
================================================
FILE: gofunction.h
================================================
#ifndef QBOX_GOPY_GOFUNCTION_H
#define QBOX_GOPY_GOFUNCTION_H
int setMethod(PyMethodDef* d, int nin);
#endif /* _GO_PYTHON_UTILS_H */
================================================
FILE: gomodule.go
================================================
package py
// #include <Python.h>
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
import "C"
import "unsafe"
// ------------------------------------------------------------------------------------------
type GoModule struct {
*Module
Ctx RegisterCtx
}
func NewGoModule(name string, doc string, self interface{}) (mod GoModule, err error) {
cName := C.CString(name)
defer C.free(unsafe.Pointer(cName))
var mdoc *C.char
if doc != "" {
mdoc = C.CString(doc)
defer C.free(unsafe.Pointer(mdoc))
}
m := C.Py_InitModule4(cName, nil, mdoc, nil, C.PYTHON_API_VERSION)
if m == nil {
err = exception()
return
}
mod.Module = (*Module)(unsafe.Pointer(m))
mod.Ctx = Register(mod.Module.Dict(), name + ".", self)
return
}
// ------------------------------------------------------------------------------------------
================================================
FILE: gomodule_test.go
================================================
package py
import (
"fmt"
"testing"
)
// ------------------------------------------------------------------------------------------
type FooModule struct {
}
func (r *FooModule) Py_bar(args *Tuple) (ret *Base, err error) {
var i int
var s []string
err = ParseV(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar:", i, s)
return IncNone(), nil
}
// ------------------------------------------------------------------------------------------
type gomoduleCase struct {
exp string
name string
}
var g_gomoduleCases = []gomoduleCase{
{
`import foo
foo.bar(1, 'Hello')
`, "test"},
}
func TestGoModule(t *testing.T) {
gomod, err := NewGoModule("foo", "", new(FooModule))
if err != nil {
t.Fatal("NewGoModule failed:", err)
}
defer gomod.Decref()
for _, c := range g_gomoduleCases {
code, err := Compile(c.exp, "", FileInput)
if err != nil {
t.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := ExecCodeModule(c.name, code.Obj())
if err != nil {
t.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
}
}
// ------------------------------------------------------------------------------------------
================================================
FILE: goregister.go
================================================
package py
import "reflect"
import "strings"
import "github.com/qiniu/log"
// ------------------------------------------------------------------------------------------
// Note: Methods take the receiver as the first argument, which the want
// signature doesn't include.
func sigMatches(got, want reflect.Type) bool {
nin := want.NumIn()
if got.NumIn()-1 != nin {
return false
}
nout := want.NumOut()
if got.NumOut() != nout {
return false
}
for i := 0; i < nin; i++ {
if got.In(i+1) != want.In(i) {
return false
}
}
for i := 0; i < nout; i++ {
if got.Out(i) != want.Out(i) {
return false
}
}
return true
}
// ------------------------------------------------------------------------------------------
var typUnaryFunc = reflect.TypeOf(func() (*Base, error)(nil))
var typBinaryCallFunc = reflect.TypeOf(func(*Tuple) (*Base, error)(nil))
var typTernaryCallFunc = reflect.TypeOf(func(*Tuple, *Dict) (*Base, error)(nil))
type RegisterCtx []*Closure // 只是让对象不被gc
func Register(dict *Dict, nsprefix string, self interface{}) (ctx RegisterCtx) {
typ := reflect.TypeOf(self)
selfv := reflect.ValueOf(self)
nmethod := typ.NumMethod()
for i := 0; i < nmethod; i++ {
method := typ.Method(i)
mtype := method.Type
mname := method.Name
if mtype.PkgPath() != "" || !strings.HasPrefix(mname, "Py_") {
continue
}
nin := mtype.NumIn()
name := mname[3:]
fullname := nsprefix + name
if nin == 3 && sigMatches(mtype, typTernaryCallFunc) || nin == 2 && sigMatches(mtype, typBinaryCallFunc) {
closure := &Closure{Self: selfv, Method: method.Func}
f := closure.NewFunction(fullname, nin, "")
dict.SetItemString(name, f)
f.Decref()
ctx = append(ctx, closure)
log.Debug("Register", fullname)
} else {
log.Warnf("Invalid signature of method %s, register failed", fullname)
continue
}
}
return
}
// ------------------------------------------------------------------------------------------
================================================
FILE: goregister_test.go
================================================
package py
import (
"testing"
"github.com/qiniu/log"
)
func init() {
log.SetOutputLevel(0)
}
// ------------------------------------------------------------------------------------------
type Foo struct {
}
func (r *Foo) Py_foo(args *Tuple) (*Base, error) {
return IncNone(), nil
}
func (r *Foo) Py_bar(args *Tuple) (*Base) {
return IncNone()
}
// ------------------------------------------------------------------------------------------
func _TestRegister(t *testing.T) {
dict := NewDict()
defer dict.Decref()
Register(dict, "", new(Foo))
}
// ------------------------------------------------------------------------------------------
================================================
FILE: int.go
================================================
// Copyright 2011 Julian Phillips. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package py
// #include <Python.h>
// static inline int intCheck(PyObject *o) { return PyInt_Check(o); }
import "C"
import "unsafe"
type Int struct {
Base
NumberProtocol
o C.PyIntObject
}
// IntType is the Type object that represents the Int type.
var IntType = (*Type)(unsafe.Pointer(&C.PyInt_Type))
func newInt(obj *C.PyObject) *Int {
return (*Int)(unsafe.Pointer(obj))
}
func NewInt(i int) *Int {
return newInt(C.PyInt_FromLong(C.long(i)))
}
func NewInt64(i int64) *Int {
return newInt(C.PyInt_FromSsize_t(C.Py_ssize_t(i)))
}
func AsInt(o *Base) (v *Int, ok bool) {
if ok = C.intCheck(o.c()) != 0; ok {
v = newInt(o.c())
}
return
}
func (i *Int) Int() int {
return int(C.PyInt_AsLong(i.c()))
}
================================================
FILE: long.go
================================================
package py
// #include <Python.h>
// static inline long longCheck(PyObject *o) { return PyLong_Check(o); }
import "C"
import "unsafe"
type Long struct {
Base
NumberProtocol
o C.PyLongObject
}
// LongType is the Type object that represents the Long type.
var LongType = (*Type)(unsafe.Pointer(&C.PyLong_Type))
func newLong(obj *C.PyObject) *Long {
return (*Long)(unsafe.Pointer(obj))
}
func NewLong(i int64) *Long {
return newLong(C.PyLong_FromLongLong(C.longlong(i)))
}
func AsLong(o *Base) (v *Long, ok bool) {
if ok = C.longCheck(o.c()) != 0; ok {
v = newLong(o.c())
}
return
}
func (l *Long) Long() int64 {
return int64(C.PyLong_AsLongLong(l.c()))
}
================================================
FILE: module.go
================================================
package py
// #include <Python.h>
// static inline int moduleCheck(PyObject *o) { return PyModule_Check(o); }
// static inline int moduleCheckE(PyObject *o) { return PyModule_CheckExact(o); }
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
import "C"
import "unsafe"
type Module struct {
Base
o C.PyObject
}
// ModuleType is the Type object that represents the Module type.
var ModuleType = (*Type)(unsafe.Pointer(&C.PyModule_Type))
func newModule(obj *C.PyObject) *Module {
return (*Module)(unsafe.Pointer(obj))
}
func Import(name string) (*Module, error) {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
pyName := C.PyString_FromString(s)
defer C.decref(pyName)
obj := C.PyImport_Import(pyName)
if obj == nil {
return nil, exception()
}
return newModule(obj), nil
}
func ExecCodeModule(name string, code *Base) (*Module, error) {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
ret := C.PyImport_ExecCodeModule(s, code.c())
if ret == nil {
return nil, exception()
}
return newModule(ret), nil
}
func NewModule(name string) (*Module, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
ret := C.PyModule_New(cname)
if ret == nil {
return nil, exception()
}
return newModule(ret), nil
}
func AsModule(o *Base) (v *Module, ok bool) {
if ok = C.moduleCheck(o.c()) != 0; ok {
v = newModule(o.c())
}
return
}
func (mod *Module) CheckExact() bool {
return C.moduleCheckE(mod.c()) != 0
}
// Return value: Borrowed reference.
func (mod *Module) Dict() *Dict {
ret := C.PyModule_GetDict(mod.c())
return newDict(ret)
}
// Return module‘s __name__ value. If the module does not provide one, or if it is not a string,
// SystemError is raised and NULL is returned.
func (mod *Module) Name() (string, error) {
ret := C.PyModule_GetName(mod.c())
if ret == nil {
return "", exception()
}
return C.GoString(ret), nil
}
func (mod *Module) Filename() (string, error) {
ret := C.PyModule_GetFilename(mod.c())
if ret == nil {
return "", exception()
}
return C.GoString(ret), nil
}
func (mod *Module) AddObject(name string, obj *Base) error {
if obj == nil {
return AssertionError.Err("ValueError: obj == nil!")
}
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
ret := C.PyModule_AddObject(mod.c(), cname, obj.c())
if ret < 0 {
return exception()
}
return nil
}
func (mod *Module) AddIntConstant(name string, value int) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
ret := C.PyModule_AddIntConstant(mod.c(), cname, C.long(value))
if ret < 0 {
return exception()
}
return nil
}
func (mod *Module) AddStringConstant(name, value string) error {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
cvalue := C.CString(value)
defer C.free(unsafe.Pointer(cvalue))
ret := C.PyModule_AddStringConstant(mod.c(), cname, cvalue)
if ret < 0 {
return exception()
}
return nil
}
================================================
FILE: module_test.go
================================================
package py
import (
"testing"
)
type moduleCase struct {
exp string
name, ret, globals string
}
var g_moduleCases = []moduleCase{
{`
tbl = 'dn_5m'
def init(cat):
global tbl
tbl = tbl + cat
return True
`, "foo", "True", "dn_5m_stage"},
}
func TestModule(t *testing.T) {
for _, c := range g_moduleCases {
code, err := Compile(c.exp, "", FileInput)
if err != nil {
t.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := ExecCodeModule(c.name, code.Obj())
if err != nil {
t.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
arg1 := NewString("_stage")
defer arg1.Decref()
ret, err := mod.CallMethodObjArgs("init", arg1.Obj())
if err != nil {
t.Fatal("CallMethodObjArgs failed:", err)
}
defer ret.Decref()
if ret.String() != c.ret {
t.Fatal("CallMethodObjArgs ret:", ret.String(), c.ret)
}
globals, _ := mod.GetAttrString("tbl")
defer globals.Decref()
if globals.String() != c.globals {
t.Fatal("mod.GetAttrString('tbl') ret:", globals.String(), c.globals)
}
dict := mod.Dict() // don't need Decref
tbl2 := dict.GetItemString("tbl") // don't need Decref
if tbl2.String() != c.globals {
t.Fatal("mod.Dict.GetItemString('tbl') ret:", tbl2.String(), c.globals)
}
}
}
================================================
FILE: none.go
================================================
package py
/*
#include <Python.h>
static inline PyObject* incNone() { Py_RETURN_NONE; }
*/
import "C"
// ------------------------------------------------------------------------------------------
func IncNone() *Base {
return newObject(C.incNone())
}
// ------------------------------------------------------------------------------------------
================================================
FILE: number.go
================================================
// Copyright 2011 Julian Phillips. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package py
// #include <Python.h>
import "C"
import "unsafe"
// NumberProtocol is a 0-sized type that can be embedded in concrete types after
// the AbstractObject to provide access to the suite of methods that Python
// calls the "Number Protocol".
type NumberProtocol struct{}
func cnp(n *NumberProtocol) *C.PyObject {
return (*C.PyObject)(unsafe.Pointer(n))
}
// Add returns the result of adding n and obj. The equivalent Python is "n +
// obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Add(obj *Base) (*Base, error) {
ret := C.PyNumber_Add(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Subtract returns the result of subtracting obj from n. The equivalent Python
// is "n - obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Subtract(obj *Base) (*Base, error) {
ret := C.PyNumber_Subtract(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Multiply returns the result of multiplying n by obj. The equivalent Python
// is "n * obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Multiply(obj *Base) (*Base, error) {
ret := C.PyNumber_Multiply(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Divide returns the result of dividing n by obj. The equivalent Python is "n
// / obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Divide(obj *Base) (*Base, error) {
ret := C.PyNumber_Divide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// FloorDivide returns the floor of dividing n obj obj.
//
// Return value: New Reference.
func (n *NumberProtocol) FloorDivide(obj *Base) (*Base, error) {
ret := C.PyNumber_FloorDivide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// TrueDivide returns the ... TODO
//
// Return value: New Reference.
func (n *NumberProtocol) TrueDivide(obj *Base) (*Base, error) {
ret := C.PyNumber_TrueDivide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Remainder returns the remainder of dividing n by obj. The equivalent Python
// is "n % obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Remainder(obj *Base) (*Base, error) {
ret := C.PyNumber_Remainder(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Divmod returns the result of the Python "divmod(n, obj)".
//
// Return value: New Reference.
func (n *NumberProtocol) Divmod(obj *Base) (*Base, error) {
ret := C.PyNumber_Divmod(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Power returns the result of the Python "pow(n, obj1, obj2)".
//
// Return value: New Reference.
func (n *NumberProtocol) Power(obj1, obj2 *Base) (*Base, error) {
ret := C.PyNumber_Power(cnp(n), obj1.c(), obj2.c())
return obj2ObjErr(ret)
}
// Negative returns the negation of n. The equivalent Python is "-n".
//
// Return value: New Reference.
func (n *NumberProtocol) Negative() (*Base, error) {
ret := C.PyNumber_Negative(cnp(n))
return obj2ObjErr(ret)
}
// Positive returns the positive of n. The equivalent Python is "+n".
//
// Return value: New Reference.
func (n *NumberProtocol) Positive() (*Base, error) {
ret := C.PyNumber_Positive(cnp(n))
return obj2ObjErr(ret)
}
// Absolute returns the absolute value of n. The equivalent Python is "abs(n)".
//
// Return value: New Reference.
func (n *NumberProtocol) Absolute() (*Base, error) {
ret := C.PyNumber_Absolute(cnp(n))
return obj2ObjErr(ret)
}
// Invert returns the bitwise negation of n. The equivalent Python is "-n".
//
// Return value: New Reference.
func (n *NumberProtocol) Invert() (*Base, error) {
ret := C.PyNumber_Invert(cnp(n))
return obj2ObjErr(ret)
}
// Lshift returns the result of left shifting n by obj. The equivalent Python
// is "n << obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Lshift(obj *Base) (*Base, error) {
ret := C.PyNumber_Lshift(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Rshift returns the result of right shifting n by obj. The equivalent Python
// is "n << obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Rshift(obj *Base) (*Base, error) {
ret := C.PyNumber_Rshift(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// And returns the bitwise and of n and obj. The equivalent Python is "n &
// obj".
//
// Return value: New Reference.
func (n *NumberProtocol) And(obj *Base) (*Base, error) {
ret := C.PyNumber_And(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Xor returns the bitwise xor of n and obj. The equivalent Python is "n ^
// obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Xor(obj *Base) (*Base, error) {
ret := C.PyNumber_Xor(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// Or returns the bitwise or of n and obj. The equivalent Python is "n | obj".
//
// Return value: New Reference.
func (n *NumberProtocol) Or(obj *Base) (*Base, error) {
ret := C.PyNumber_Or(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceAdd returns the result of adding n and obj. This is done in place if
// supported by n. The equivalent Python is "n += obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceAdd(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceAdd(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceSubtract returns the result of subtracting obj from n. This is done
// in place if supported by n. The equivalent Python is "n -= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceSubtract(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceSubtract(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceMultiply returns the result of multiplying n by obj. This is done in
// place if supported by n. The equivalent Python is "n *= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceMultiply(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceMultiply(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceDivide returns the result of dividing n by obj. This is done in place
// if supported by n. The equivalent Python is "n /= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceDivide(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceDivide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// TODO returns the ...
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceFloorDivide(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceFloorDivide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// TODO returns the ...
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceTrueDivide(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceTrueDivide(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceRemainder returns the remainder of n divided by obj. This is done in
// place if supported by n. The equivalent Python is "n %= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceRemainder(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceRemainder(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlacePower returns the result of the Python "pow(n, obj1, obj2)". This is
// done in place if supported by n. If obj2 is None, then the Python "n **=
// obj" is also equivalent, if obj2 is not None, there is no equivalent in
// Python.
//
// Return value: New Reference.
func (n *NumberProtocol) InPlacePower(obj1, obj2 *Base) (*Base, error) {
ret := C.PyNumber_InPlacePower(cnp(n), obj1.c(), obj2.c())
return obj2ObjErr(ret)
}
// InPlaceLshift returns the result of left shifting n by obj. This is done in
// place if supported by n. The equivalent Python is "n <<= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceLshift(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceLshift(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceRshift returns the result of right shifting n by obj. This is done in
// place if supported by n. The equivalent Python is "n >>= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceRshift(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceRshift(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceAnd returns the bitwise and of n and obj. This is done in place if
// supported by n. The equivalent Python is "n &= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceAnd(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceAnd(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceXor returns the bitwise xor of n and obj. This is done in place if
// supported by n. The equivalent Python is "n ^= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceXor(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceXor(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// InPlaceOr returns the bitwise or of n and obj. This is done in place if
// supported by n. The equivalent Python is "n |= obj".
//
// Return value: New Reference.
func (n *NumberProtocol) InPlaceOr(obj *Base) (*Base, error) {
ret := C.PyNumber_InPlaceOr(cnp(n), obj.c())
return obj2ObjErr(ret)
}
// PyNumber_Coerce: TODO
// PyNumber_CoerceEx: TODO
// PyNumber_Int: TODO
// PyNumber_Long: TODO
// PyNumber_Float: TODO
// PyNumber_Index: TODO
// PyNumber_ToBase: TODO
// PyNumber_AsSsize_t: TODO
================================================
FILE: object.go
================================================
package py
// #include <Python.h>
// static inline void incref(PyObject *obj) { Py_INCREF(obj); }
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
import "C"
import "unsafe"
type Op int
const (
LT = Op(C.Py_LT)
LE = Op(C.Py_LE)
EQ = Op(C.Py_EQ)
NE = Op(C.Py_NE)
GT = Op(C.Py_GT)
GE = Op(C.Py_GE)
)
// Base is an 0-sized type that can be embedded as the first item in
// concrete types to provide the Object interface functions.
type Base struct {}
func newObject(obj *C.PyObject) *Base {
return (*Base)(unsafe.Pointer(obj))
}
func (obj *Base) c() *C.PyObject {
return (*C.PyObject)(unsafe.Pointer(obj))
}
func (obj *Base) Obj() *Base {
return obj
}
// Init initialises obj. It is equivalent to "obj.__init__(*args, **kw)" in
// Python.
func (obj *Base) Init(args *Tuple, kw *Dict) error {
return obj.Type().Init(obj, args, kw)
}
// Type returns a pointer to the Type that represents the type of this object in
// Python.
func (obj *Base) Type() *Type {
o := obj.c().ob_type
return newType((*C.PyObject)(unsafe.Pointer(o)))
}
// Decref decrements obj's reference count, obj may not be nil.
func (obj *Base) Decref() {
C.decref(obj.c())
}
// Incref increments obj's reference count, obj may not be nil.
func (obj *Base) Incref() {
C.incref(obj.c())
}
// IsTrue returns true if the value of obj is considered to be True. This is
// equivalent to "if obj:" in Python.
func (obj *Base) IsTrue() bool {
ret := C.PyObject_IsTrue(obj.c())
if ret < 0 {
panic(exception())
}
return ret != 0
}
// Not returns true if the value of obj is considered to be False. This is
// equivalent to "if not obj:" in Python.
func (obj *Base) Not() bool {
ret := C.PyObject_Not(obj.c())
if ret < 0 {
panic(exception())
}
return ret != 0
}
// HasAttr returns true if "obj" has the attribute "name". This is equivalent
// to the Python "hasattr(obj, name)".
func (obj *Base) HasAttr(name *Base) bool {
ret := C.PyObject_HasAttr(obj.c(), name.c())
if ret == 1 {
return true
}
return false
}
// HasAttrString returns true if "obj" has the attribute "name". This is
// equivalent to the Python "hasattr(obj, name)".
func (obj *Base) HasAttrString(name string) bool {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
ret := C.PyObject_HasAttrString(obj.c(), s)
if ret == 1 {
return true
}
return false
}
// GetAttr returns the attribute of "obj" with the name "name". This is
// equivalent to the Python "obj.name".
//
// Return value: New Reference.
func (obj *Base) GetAttr(name *Base) (*Base, error) {
ret := C.PyObject_GetAttr(obj.c(), name.c())
return obj2ObjErr(ret)
}
// Retrieve an attribute named attr_name from object o. Returns the attribute value
// on success, or NULL on failure. This is the equivalent to the Python "obj.name".
//
// Return value: New reference.
func (obj *Base) GetAttrString(name string) (*Base, error) {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
ret := C.PyObject_GetAttrString(obj.c(), s)
return obj2ObjErr(ret)
}
// PyObject_GenericGetAttr : This is an internal helper function - we shouldn't
// need to expose it ...
// SetAttr sets the attribute of "obj" with the name "name" to "value". This is
// equivalent to the Python "obj.name = value".
func (obj *Base) SetAttr(name, value *Base) error {
ret := C.PyObject_SetAttr(obj.c(), name.c(), value.c())
return int2Err(ret)
}
// SetAttrString sets the attribute of "obj" with the name "name" to "value".
// This is equivalent to the Python "obj.name = value".
func (obj *Base) SetAttrString(name string, value *Base) error {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
ret := C.PyObject_SetAttrString(obj.c(), s, value.c())
return int2Err(ret)
}
// PyObject_GenericSetAttr : This is an internal helper function - we shouldn't
// need to expose it ...
// DelAttr deletes the attribute with the name "name" from "obj". This is
// equivalent to the Python "del obj.name".
func (obj *Base) DelAttr(name *Base) error {
ret := C.PyObject_SetAttr(obj.c(), name.c(), nil)
return int2Err(ret)
}
// DelAttrString deletes the attribute with the name "name" from "obj". This is
// equivalent to the Python "del obj.name".
func (obj *Base) DelAttrString(name string) error {
s := C.CString(name)
defer C.free(unsafe.Pointer(s))
ret := C.PyObject_SetAttrString(obj.c(), s, nil)
return int2Err(ret)
}
// RichCompare compares "obj" with "obj2" using the specified operation (LE, GE
// etc.), and returns the result. The equivalent Python is "obj op obj2", where
// op is the corresponding Python operator for op.
//
// Return value: New Reference.
func (obj *Base) RichCompare(obj2 *Base, op Op) (*Base, error) {
ret := C.PyObject_RichCompare(obj.c(), obj2.c(), C.int(op))
return obj2ObjErr(ret)
}
// RichCompare compares "obj" with "obj2" using the specified operation (LE, GE
// etc.), and returns true or false. The equivalent Python is "obj op obj2",
// where op is the corresponding Python operator for op.
func (obj *Base) RichCompareBool(obj2 *Base, op Op) (bool, error) {
ret := C.PyObject_RichCompareBool(obj.c(), obj2.c(), C.int(op))
return int2BoolErr(ret)
}
// PyObject_Cmp : Thanks to multiple return values, we don't need this function
// to be available in Go.
// Compare returns the result of comparing "obj" and "obj2". This is equivalent
// to the Python "cmp(obj, obj2)".
func (obj *Base) Compare(obj2 *Base) (int, error) {
ret := C.PyObject_Compare(obj.c(), obj2.c())
return int(ret), exception()
}
// Repr returns a String representation of "obj". This is equivalent to the
// Python "repr(obj)".
//
// Return value: New Reference.
func (obj *Base) Repr() (*Base, error) {
ret := C.PyObject_Repr(obj.c())
return obj2ObjErr(ret)
}
// Str returns a String representation of "obj". This is equivalent to the
// Python "str(obj)".
//
// Return value: New Reference.
func (obj *Base) Str() (*Base, error) {
ret := C.PyObject_Str(obj.c())
return obj2ObjErr(ret)
}
func (obj *Base) String() string {
if v, ok := AsString(obj); ok {
return v.String()
}
ret := C.PyObject_Str(obj.c())
if ret == nil {
return "<nil>"
}
defer C.decref(ret)
return ((*String)(unsafe.Pointer(ret))).String()
}
// Bytes returns a Bytes representation of "obj". This is equivalent to the
// Python "bytes(obj)". In Python 2.x this method is identical to Str().
//
// Return value: New Reference.
func (obj *Base) Bytes() (*Base, error) {
ret := C.PyObject_Bytes(obj.c())
return obj2ObjErr(ret)
}
// PyObject_Unicode : TODO
// IsInstance returns true if "obj" is an instance of "cls", false otherwise.
// If "cls" is a Type instead of a class, then true will be return if "obj" is
// of that type. If "cls" is a Tuple then true will be returned if "obj" is an
// instance of any of the Objects in the tuple. This is equivalent to the
// Python "isinstance(obj, cls)".
func (obj *Base) IsInstance(cls *Base) (bool, error) {
ret := C.PyObject_IsInstance(obj.c(), cls.c())
return int2BoolErr(ret)
}
// IsSubclass retuns true if "obj" is a Subclass of "cls", false otherwise. If
// "cls" is a Tuple, then true is returned if "obj" is a Subclass of any member
// of "cls". This is equivalent to the Python "issubclass(obj, cls)".
func (obj *Base) IsSubclass(cls *Base) (bool, error) {
ret := C.PyObject_IsSubclass(obj.c(), cls.c())
return int2BoolErr(ret)
}
// Call calls obj with the given args and kwds. kwds may be nil, args may not
// (an empty Tuple must be used if no arguments are wanted). Returns the result
// of the call, or an Error on failure. This is equivalent to
// "obj(*args, **kwds)" in Python.
//
// Return value: New Reference.
func (obj *Base) Call(args *Tuple, kwds *Dict) (*Base, error) {
ret := C.PyObject_Call(obj.c(), args.c(), kwds.c())
return obj2ObjErr(ret)
}
// CallObject calls obj with the given args. args may be nil. Returns the
// result of the call, or an Error on failure. This is equivalent to
// "obj(*args)" in Python.
//
// Return value: New Reference.
func (obj *Base) CallObject(args *Tuple) (*Base, error) {
var a *C.PyObject = nil
if args != nil {
a = args.c()
}
ret := C.PyObject_CallObject(obj.c(), a)
return obj2ObjErr(ret)
}
func (obj *Base) CallMethodObject(name string, args *Tuple) (*Base, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
f := C.PyObject_GetAttrString(obj.c(), cname)
if f == nil {
return nil, AttributeError.Err(name)
}
defer C.decref(f)
if C.PyCallable_Check(f) == 0 {
return nil, TypeError.Err("attribute of type '%s' is not callable", name)
}
ret := C.PyObject_CallObject(f, args.c())
return obj2ObjErr(ret)
}
func (obj *Base) CallObjArgs(args ...*Base) (*Base, error) {
args1 := PackTuple(args...)
defer args1.Decref()
return obj.CallObject(args1)
}
func (obj *Base) CallMethodObjArgs(name string, args ...*Base) (*Base, error) {
args1 := PackTuple(args...)
defer args1.Decref()
return obj.CallMethodObject(name, args1)
}
// PyObject_Hash : TODO
// PyObject_HashNotImplement : This is an internal function, that we probably
// don't need to export.
// Length returns the length of the Object. This is equivalent to the Python
// "len(obj)".
func (obj *Base) Length() (int64, error) {
ret := C.PyObject_Length(obj.c())
return int64(ret), exception()
}
// Size returns the length of the Object. This is equivalent to the Python
// "len(obj)".
func (obj *Base) Size() (int64, error) {
ret := C.PyObject_Size(obj.c())
return int64(ret), exception()
}
// GetItem returns the element of "obj" corresponding to "key". This is
// equivalent to the Python "obj[key]".
//
// Return value: New Reference.
func (obj *Base) GetItem(key *Base) (*Base, error) {
ret := C.PyObject_GetItem(obj.c(), key.c())
return obj2ObjErr(ret)
}
// SetItem sets the element of "obj" corresponding to "key" to "value". This is
// equivalent to the Python "obj[key] = value".
func (obj *Base) SetItem(key, value *Base) error {
ret := C.PyObject_SetItem(obj.c(), key.c(), value.c())
return int2Err(ret)
}
// DelItem deletes the element from "obj" that corresponds to "key". This is
// equivalent to the Python "del obj[key]".
func (obj *Base) DelItem(key *Base) error {
ret := C.PyObject_DelItem(obj.c(), key.c())
return int2Err(ret)
}
// PyObject_AsFileDescriptor : TODO
func (obj *Base) Dir() (*Base, error) {
ret := C.PyObject_Dir(obj.c())
return obj2ObjErr(ret)
}
// PyObject_GetIter : TODO
================================================
FILE: object_test.go
================================================
package py
import (
"testing"
)
func TestBase(t *testing.T) {
{
v := NewString("Hello!")
defer v.Decref()
if v.String() != "Hello!" {
t.Fatal("NewString failed")
}
}
{
v := NewInt(1)
defer v.Decref()
if v.String() != "1" {
t.Fatal("NewInt failed")
}
}
{
v1 := NewInt(1)
defer v1.Decref()
v2 := NewString("Hello!")
defer v2.Decref()
v := PackTuple(v1.Obj(), v2.Obj())
defer v.Decref()
if v.String() != "(1, 'Hello!')" {
t.Fatal("NewTuple failed:", v.String())
}
}
{
v1 := NewInt(1)
defer v1.Decref()
v2 := NewString("Hello!")
defer v2.Decref()
v := NewDict()
defer v.Decref()
v.SetItem(v1.Obj(), v2.Obj())
if v.String() != "{1: 'Hello!'}" {
t.Fatal("NewDict failed:", v.String())
}
}
}
================================================
FILE: python.go
================================================
package py
/*
#cgo pkg-config: python-2.7
#include <Python.h>
static inline int enterRecursive(char *w) {
return Py_EnterRecursiveCall(w);
}
static inline void leaveRecursive() {
Py_LeaveRecursiveCall();
}
*/
import "C"
import "unsafe"
func init() {
C.Py_Initialize()
}
func Initialize() {
C.Py_Initialize()
}
func InitializeEx(initsigs bool) {
if initsigs {
C.Py_InitializeEx(1)
} else {
C.Py_InitializeEx(0)
}
}
func Finalize() {
C.Py_Finalize()
}
func AddToPath(dir string) {
p := C.CString("path")
defer C.free(unsafe.Pointer(p))
sys_path := C.PySys_GetObject(p)
if sys_path == nil {
return
}
s := C.CString(dir)
defer C.free(unsafe.Pointer(s))
pDir := C.PyString_FromString(s)
if pDir == nil {
return
}
C.PyList_Append(sys_path, pDir)
}
func Main(args []string) int {
argv := make([]*C.char, len(args))
for i, arg := range args {
argv[i] = C.CString(arg)
defer C.free(unsafe.Pointer(argv[i]))
}
return int(C.Py_Main(C.int(len(argv)), &argv[0]))
}
// EnterRecusiveCall marks a point where a recursive Go-level call is about to
// be performed. It returns true if the recursive call is permitted, otherwise
// a Python exception is set and false is returned. where is a string that will
// be appended to the RuntimeError set if the recursion limit has been exceeded
// (e.g. " in instance check"). This function needs to be called if the
// recursive function may not invoke Python code (which automatically tracks
// recursion depth).
func EnterRecursiveCall(where string) bool {
s := C.CString(where)
defer C.free(unsafe.Pointer(s))
return C.enterRecursive(s) == 0
}
// LeaveRecursiveCall must be called after a recursive call that was indicated
// by EnterRecursiveCall.
func LeaveRecursiveCall() {
C.leaveRecursive()
}
================================================
FILE: pyutil/call.go
================================================
package pyutil
import (
"syscall"
"github.com/qiniu/py"
"github.com/qiniu/errors"
)
// ------------------------------------------------------------------------------------------
func PackEx(cfg *Config, args ...interface{}) (ret *py.Tuple, err error) {
args1 := py.NewTuple(len(args))
for i, arg := range args {
v1, ok1 := NewVarEx(arg, cfg)
if !ok1 {
args1.Decref()
err = errors.Info(syscall.EINVAL, "pyutil.Pack", i+1, arg).Detail(err)
return
}
args1.SetItem(i, v1)
}
return args1, nil
}
func Pack(args ...interface{}) (ret *py.Tuple, err error) {
return PackEx(DefaultConfig, args...)
}
// ------------------------------------------------------------------------------------------
func CallEx(cfg *Config, fn *py.Base, args ...interface{}) (ret *py.Base, err error) {
args1, err := PackEx(cfg, args...)
if err != nil {
err = errors.Info(syscall.EINVAL, "pyutil.Call").Detail(err)
return
}
defer args1.Decref()
return fn.CallObject(args1)
}
func Call(fn *py.Base, args ...interface{}) (*py.Base, error) {
return CallEx(DefaultConfig, fn, args...)
}
// ------------------------------------------------------------------------------------------
func CallMethodEx(cfg *Config, self *py.Base, method string, args ...interface{}) (ret *py.Base, err error) {
args1, err := PackEx(cfg, args...)
if err != nil {
err = errors.Info(syscall.EINVAL, "pyutil.Call").Detail(err)
return
}
defer args1.Decref()
return self.CallMethodObject(method, args1)
}
func CallMethod(self *py.Base, method string, args ...interface{}) (ret *py.Base, err error) {
return CallMethodEx(DefaultConfig, self, method, args...)
}
// ------------------------------------------------------------------------------------------
func NewInstanceEx(cfg *Config, typ *py.Class, args ...interface{}) (ret *py.Base, err error) {
args1, err := PackEx(cfg, args...)
if err != nil {
err = errors.Info(syscall.EINVAL, "pyutil.NewInstance").Detail(err)
return
}
defer args1.Decref()
return typ.New(args1, nil)
}
func NewInstance(typ *py.Class, args ...interface{}) (ret *py.Base, err error) {
return NewInstanceEx(DefaultConfig, typ, args...)
}
// ------------------------------------------------------------------------------------------
func NewEx(cfg *Config, mod *py.Base, clsname string, args ...interface{}) (ret *py.Base, err error) {
o, err := mod.GetAttrString(clsname)
if err != nil {
err = errors.Info(err, "pyutil.New", clsname).Detail(err)
return
}
defer o.Decref()
ty, ok := py.AsClass(o)
if !ok {
err = errors.Info(syscall.EINVAL, "pyutil.New", o.String(), "is not a class")
return
}
return NewInstanceEx(cfg, ty, args...)
}
func New(mod *py.Base, clsname string, args ...interface{}) (ret *py.Base, err error) {
return NewEx(DefaultConfig, mod, clsname, args...)
}
// ------------------------------------------------------------------------------------------
================================================
FILE: pyutil/call_test.go
================================================
package pyutil
import (
"testing"
"github.com/qiniu/log"
"github.com/qiniu/errors"
"github.com/qiniu/py"
)
type moduleCase struct {
exp string
name, ret, tbl string
}
var g_moduleCases = []moduleCase{
{`
class Plugin:
def init(self, cate):
self.tbl = "dn_5m" + cate
`, "foo", "None", "dn_5m_stage"},
}
func TestCall(t *testing.T) {
log.SetOutputLevel(0)
for _, c := range g_moduleCases {
code, err := py.Compile(c.exp, "", py.FileInput)
if err != nil {
t.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := py.ExecCodeModule(c.name, code.Obj())
if err != nil {
t.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
plg, err := New(mod.Obj(), "Plugin")
if err != nil {
t.Fatal("NewPlugin failed:", errors.Detail(err))
}
ret, err := CallMethod(plg, "init", "_stage")
if err != nil {
t.Fatal("CallMethod failed:", err)
}
defer ret.Decref()
if ret.String() != c.ret {
t.Fatal("CallMethod ret:", ret.String(), c.ret)
}
tbl, _ := plg.GetAttrString("tbl")
if tbl.String() != c.tbl {
t.Fatal("mod.GetAttrString('tbl') ret:", tbl.String(), c.tbl)
}
}
}
================================================
FILE: pyutil/var.go
================================================
package pyutil
import (
"strings"
"reflect"
"github.com/qiniu/py"
)
// ------------------------------------------------------------------------------------------
type Config struct {
Cate string
SliceAsList bool
}
var DefaultConfig = &Config {
Cate: "json",
}
// ------------------------------------------------------------------------------------------
func tagName(tag string) (string) {
if idx := strings.Index(tag, ","); idx != -1 {
return tag[:idx]
}
return tag
}
func newStruct(sv reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
dict := py.NewDict()
st := sv.Type()
for i := 0; i < sv.NumField(); i++ {
sf := st.Field(i)
tag := sf.Tag.Get(cfg.Cate)
if tag == "" {
return nil, false
}
name := tagName(tag)
val := sv.Field(i)
val1, ok1 := NewVarEx(val.Interface(), cfg)
if !ok1 {
dict.Decref()
return nil, false
}
dict.SetItemString(name, val1)
val1.Decref()
}
return dict.Obj(), true
}
func newMap(v reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
dict := py.NewDict()
keys := v.MapKeys()
for _, key := range keys {
key1, ok1 := NewVarEx(key.Interface(), cfg)
if !ok1 {
dict.Decref()
return nil, false
}
val1, ok1 := NewVarEx(v.MapIndex(key).Interface(), cfg)
if !ok1 {
key1.Decref()
dict.Decref()
return nil, false
}
dict.SetItem(key1, val1)
key1.Decref()
val1.Decref()
}
return dict.Obj(), true
}
func newComplex(val reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
retry:
switch val.Kind() {
case reflect.Struct:
return newStruct(val, cfg)
case reflect.Map:
return newMap(val, cfg)
case reflect.Ptr, reflect.Interface:
val = val.Elem()
goto retry
}
return nil, false
}
// ------------------------------------------------------------------------------------------
func NewVarEx(val interface{}, cfg *Config) (ret *py.Base, ok bool) {
switch v := val.(type) {
case int:
return py.NewInt(v).Obj(), true
case int64:
return py.NewLong(v).Obj(), true
case string:
return py.NewString(v).Obj(), true
}
return newComplex(reflect.ValueOf(val), cfg)
}
func NewVar(val interface{}) (ret *py.Base, ok bool) {
return NewVarEx(val, DefaultConfig)
}
// ------------------------------------------------------------------------------------------
================================================
FILE: pyutil/var_test.go
================================================
package pyutil
import (
"testing"
"github.com/qiniu/py"
)
type Foo struct {
A int `json:"a"`
B string `json:"b"`
}
func Test(t *testing.T) {
{
val, ok := NewVar(1)
if !ok {
t.Fatal("NewVar failed")
}
if v, ok := py.AsInt(val); !ok || v.Int() != 1 {
t.Fatal("NewVar failed:", val)
}
}
{
val, ok := NewVar(int64(1))
if !ok {
t.Fatal("NewVar failed")
}
if v, ok := py.AsLong(val); !ok || v.Long() != 1 {
t.Fatal("NewVar failed:", val)
}
}
{
val, ok := NewVar("Hello")
if !ok {
t.Fatal("NewVar failed")
}
if v, ok := py.AsString(val); !ok || v.String() != "Hello" {
t.Fatal("NewVar failed:", val)
}
}
{
foo := &Foo{
A: 1, B: "Hello",
}
val, ok := NewVar(foo)
if !ok {
t.Fatal("NewVar failed")
}
if v, ok := py.AsDict(val); !ok || !checkFoo(v, t) {
t.Fatal("NewVar failed:", val)
}
}
{
foo := map[string]interface{}{
"a": 1, "b": "Hello",
}
val, ok := NewVar(foo)
if !ok {
t.Fatal("NewVar failed")
}
if v, ok := py.AsDict(val); !ok || !checkFoo(v, t) {
t.Fatal("NewVar failed:", val)
}
}
}
func checkFoo(val *py.Dict, t *testing.T) bool {
a := val.GetItemString("a")
if a == nil {
t.Fatal("GetItemString a failed")
return false
}
if v, ok := py.AsInt(a); !ok || v.Int() != 1 {
t.Fatal("GetItemString a failed")
}
b := val.GetItemString("b")
if b == nil {
t.Fatal("GetItemString b failed")
return false
}
if v, ok := py.AsString(b); !ok || v.String() != "Hello" {
t.Fatal("GetItemString b failed")
}
return true
}
================================================
FILE: string.go
================================================
package py
// #include <Python.h>
// static inline int stringCheck(PyObject *o) { return PyString_Check(o); }
import "C"
import "unsafe"
type String struct {
Base
o C.PyStringObject
}
// StringType is the Type object that represents the String type.
var StringType = (*Type)(unsafe.Pointer(&C.PyString_Type))
func newString(obj *C.PyObject) *String {
return (*String)(unsafe.Pointer(obj))
}
func NewString(s string) *String {
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
ret := C.PyString_FromString(cs)
return newString(ret)
}
func AsString(o *Base) (v *String, ok bool) {
if ok = C.stringCheck(o.c()) != 0; ok {
v = newString(o.c())
}
return
}
func (s *String) String() string {
if s == nil {
return "<nil>"
}
ret := C.PyString_AsString(s.c())
return C.GoString(ret)
}
func (s *String) Format(args *Tuple) (*String, error) {
ret := C.PyString_Format(s.c(), args.c())
if ret == nil {
return nil, exception()
}
return newString(ret), nil
}
================================================
FILE: tuple.go
================================================
package py
// #include <Python.h>
// static inline int tupleCheckE(PyObject *o) { return PyTuple_CheckExact(o); }
// static inline int tupleCheck(PyObject *o) { return PyTuple_Check(o); }
// static inline size_t tupleItemSize() { return sizeof(PyObject *); }
import "C"
import "unsafe"
type Tuple struct {
Base
o C.PyTupleObject
}
// TupleType is the Type object that represents the Tuple type.
var TupleType = (*Type)(unsafe.Pointer(&C.PyTuple_Type))
func newTuple(obj *C.PyObject) *Tuple {
return (*Tuple)(unsafe.Pointer(obj))
}
// NewTuple returns a new *Tuple of the specified size. However the entries are
// all set to NULL, so the tuple should not be shared, especially with Python
// code, until the entries have all been set.
//
// Return value: New Reference.
func NewTuple(size int) *Tuple {
ret := C.PyTuple_New(C.Py_ssize_t(size))
return newTuple(ret)
}
func AsTuple(o *Base) (v *Tuple, ok bool) {
if ok = C.tupleCheck(o.c()) != 0; ok {
v = newTuple(o.c())
}
return
}
// PackTuple returns a new *Tuple which contains the arguments. This tuple is
// ready to use.
//
// Return value: New Reference.
func PackTuple(items ...*Base) *Tuple {
ret := C.PyTuple_New(C.Py_ssize_t(len(items)))
// Since the ob_item array has a size of 1, Go won't let us index more than
// a single entry, and if we try and use our own local type definition with
// a flexible array member then cgo converts it to [0]byte which is even
// less useful. So, we resort to pointer manipulation - which is
// unfortunate, as it's messy in Go.
// base is a pointer to the first item in the array of PyObject pointers.
// step is the size of a PyObject * (i.e. the number of bytes we need to add
// to get to the next item).
base := unsafe.Pointer(&(*C.PyTupleObject)(unsafe.Pointer(ret)).ob_item[0])
step := uintptr(C.tupleItemSize())
for _, item := range items {
item.Incref()
*(**C.PyObject)(base) = item.c()
// Move base to point to the next item, by incrementing by step bytes
base = unsafe.Pointer(uintptr(base) + step)
}
return newTuple(ret)
}
func (t *Tuple) CheckExact() bool {
ret := C.tupleCheckE(t.c())
if int(ret) != 0 {
return true
}
return false
}
func (t *Tuple) Size() int {
ret := C.PyTuple_Size(t.c())
if ret < 0 {
panic(exception())
}
return int(ret)
}
// Return the object at position pos in the tuple pointed to by p. If pos is out of bounds,
// return NULL and sets an IndexError exception.
//
// Return value: Borrowed reference.
func (t *Tuple) GetItem(pos int) (*Base, error) {
ret := C.PyTuple_GetItem(t.c(), C.Py_ssize_t(pos))
return obj2ObjErr(ret)
}
func (t *Tuple) GetSlice(low, high int) (*Tuple, error) {
ret := C.PyTuple_GetSlice(t.c(), C.Py_ssize_t(low), C.Py_ssize_t(high))
if ret == nil {
return nil, exception()
}
return newTuple(ret), nil
}
// Insert a reference to object o at position pos of the tuple pointed to by p. Return 0 on success.
// Note This function “steals” a reference to o.
func (t *Tuple) SetItem(pos int, obj *Base) error {
ret := C.PyTuple_SetItem(t.c(), C.Py_ssize_t(pos), obj.c())
return int2Err(ret)
}
// _PyTuple_Resize
// PyTuple_ClearFreeList()
func (t *Tuple) Slice() []*Base {
l := t.Size()
s := make([]*Base, l)
for i := 0; i < l; i++ {
o, err := t.GetItem(i)
if err != nil {
panic(err)
}
s[i] = o
}
return s
}
================================================
FILE: type.go
================================================
package py
// #include <Python.h>
// static inline int typeCheck(PyObject *o) { return PyType_Check(o); }
// static inline int typeCheckE(PyObject *o) { return PyType_CheckExact(o); }
// static inline PyObject* typeAlloc(PyObject *t, Py_ssize_t n) {
// return ((PyTypeObject*)t)->tp_alloc((PyTypeObject *)t, n);
// }
// static inline int typeInit(PyObject *t, PyObject *o, PyObject *a, PyObject *k) {
// return ((PyTypeObject*)t)->tp_init(o, a, k);
// }
// static inline PyObject* typeNew(PyObject *t, PyObject *a, PyObject *k) {
// return ((PyTypeObject*)t)->tp_new((PyTypeObject*)t, a, k);
// }
import "C"
import "unsafe"
type Type struct {
Base
o C.PyTypeObject
}
// TypeType is the Type object that represents the Type type.
var TypeType = (*Type)(unsafe.Pointer(&C.PyType_Type))
func newType(obj *C.PyObject) *Type {
return (*Type)(unsafe.Pointer(obj))
}
func AsType(o *Base) (v *Type, ok bool) {
if ok = C.typeCheck(o.c()) != 0; ok {
v = newType(o.c())
}
return
}
func (t *Type) NewNoArgs() (ret *Base, err error) {
args := NewTuple(0)
defer args.Decref()
return t.New(args, nil)
}
func (t *Type) New(args *Tuple, kw *Dict) (ret *Base, err error) {
ret1 := C.typeNew(t.c(), args.c(), kw.c())
return obj2ObjErr(ret1)
}
func (t *Type) NewObjArgs(args ...*Base) (ret *Base, err error) {
args1 := PackTuple(args...)
defer args1.Decref()
return t.New(args1, nil)
}
func (t *Type) Alloc(n int64) (*Base, error) {
ret := C.typeAlloc(t.c(), C.Py_ssize_t(n))
return obj2ObjErr(ret)
}
func (t *Type) Init(obj *Base, args *Tuple, kw *Dict) error {
ret := C.typeInit(t.c(), obj.c(), args.c(), kw.c())
if ret < 0 {
return exception()
}
return nil
}
// CheckExact returns true when "t" is an actual Type object, and not some form
// of subclass.
func (t *Type) CheckExact() bool {
return C.typeCheckE(t.c()) == 1
}
// PyType_ClearCache : TODO - ???
// Modified should be called after the attributes or base class of a Type have
// been changed.
func (t *Type) Modified() {
C.PyType_Modified(&t.o)
}
// HasFeature returns true when "t" has the feature in question.
func (t *Type) HasFeature(feature uint32) bool {
return (t.o.tp_flags & C.long(feature)) != 0
}
// IsGc returns true if the type "t" supports Cyclic Garbage Collection.
func (t *Type) IsGc() bool {
return t.HasFeature(C.Py_TPFLAGS_HAVE_GC)
}
// IsSubtype returns true if "t" is a subclass of "t2".
func (t *Type) IsSubtype(t2 *Type) bool {
return C.PyType_IsSubtype(&t.o, &t2.o) == 1
}
// PyType_GenericAlloc : This is an internal function, which we should not need
// to expose.
// PyType_GenericNew : Another internal function we don't need to expose.
// PyType_Ready : This function is wrapped (along with a lot of other
// functionality) in the Create method of the Class stuct.
gitextract_iqe7pocv/ ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── class.go ├── code.go ├── code_test.go ├── dict.go ├── error.go ├── examples/ │ └── gomodule/ │ └── gomodule.go ├── exc.go ├── exception.go ├── float.go ├── goargs.go ├── gofunction.c ├── gofunction.go ├── gofunction.h ├── gomodule.go ├── gomodule_test.go ├── goregister.go ├── goregister_test.go ├── int.go ├── long.go ├── module.go ├── module_test.go ├── none.go ├── number.go ├── object.go ├── object_test.go ├── python.go ├── pyutil/ │ ├── call.go │ ├── call_test.go │ ├── var.go │ └── var_test.go ├── string.go ├── tuple.go └── type.go
SYMBOL INDEX (273 symbols across 31 files)
FILE: class.go
type Class (line 8) | type Class struct
method NewNoArgs (line 27) | func (t *Class) NewNoArgs() (ret *Base, err error) {
method New (line 36) | func (t *Class) New(args *Tuple, kw *Dict) (ret *Base, err error) {
method NewObjArgs (line 41) | func (t *Class) NewObjArgs(args ...*Base) (ret *Base, err error) {
method IsSubclass (line 48) | func (t *Class) IsSubclass(base *Base) bool {
function newClass (line 16) | func newClass(obj *C.PyObject) *Class {
function AsClass (line 20) | func AsClass(o *Base) (v *Class, ok bool) {
FILE: code.go
type StartToken (line 29) | type StartToken
constant EvalInput (line 32) | EvalInput = StartToken(C.Py_eval_input)
constant FileInput (line 34) | FileInput = StartToken(C.Py_file_input)
constant SingleInput (line 37) | SingleInput = StartToken(C.Py_single_input)
type Code (line 43) | type Code struct
method Eval (line 94) | func (code *Code) Eval(globals, locals *Base) (*Base, error) {
method Run (line 100) | func (code *Code) Run(globals, locals *Base) error {
function newCode (line 51) | func newCode(obj *C.PyObject) *Code {
function AsCode (line 55) | func AsCode(o *Base) (v *Code, ok bool) {
function Compile (line 62) | func Compile(text, filename string, start StartToken) (*Code, error) {
function CompileFile (line 76) | func CompileFile(name string, start StartToken) (*Code, error) {
function Run (line 112) | func Run(text string) error {
function GetBuiltins (line 125) | func GetBuiltins() *Base {
function GetLocals (line 134) | func GetLocals() *Base {
function GetGlobals (line 143) | func GetGlobals() *Base {
FILE: code_test.go
type compileCase (line 7) | type compileCase struct
function TestCompile (line 19) | func TestCompile(t *testing.T) {
type evalLocalGlobalsCase (line 46) | type evalLocalGlobalsCase struct
function _TestEvalLocalGlobals (line 59) | func _TestEvalLocalGlobals(t *testing.T) {
FILE: dict.go
type Dict (line 12) | type Dict struct
method CheckExact (line 46) | func (d *Dict) CheckExact() bool {
method Clear (line 55) | func (d *Dict) Clear() {
method Contains (line 61) | func (d *Dict) Contains(key *Base) (bool, error) {
method Copy (line 69) | func (d *Dict) Copy() (*Base, error) {
method SetItem (line 76) | func (d *Dict) SetItem(key, val *Base) error {
method SetItemString (line 84) | func (d *Dict) SetItemString(key string, val *Base) error {
method DelItem (line 93) | func (d *Dict) DelItem(key *Base) error {
method DelItemString (line 100) | func (d *Dict) DelItemString(key string) error {
method GetItem (line 111) | func (d *Dict) GetItem(key *Base) *Base {
method GetItemString (line 121) | func (d *Dict) GetItemString(key string) *Base {
method Size (line 159) | func (d *Dict) Size() int {
method Merge (line 173) | func (d *Dict) Merge(o *Base, override bool) error {
method Update (line 184) | func (d *Dict) Update(o *Base) error {
method MergeFromSeq2 (line 194) | func (d *Dict) MergeFromSeq2(o *Base, override bool) error {
method Map (line 209) | func (d *Dict) Map() map[*Base]*Base {
method MapString (line 226) | func (d *Dict) MapString() (map[string]*Base, error) {
method Next (line 249) | func (d *Dict) Next(pos *DictIter, k, v **Base) bool {
function newDict (line 20) | func newDict(obj *C.PyObject) *Dict {
function NewDict (line 27) | func NewDict() *Dict {
function NewDictProxy (line 32) | func NewDictProxy(obj *Base) *Dict {
function AsDict (line 37) | func AsDict(o *Base) (v *Dict, ok bool) {
type DictIter (line 240) | type DictIter
FILE: error.go
type Error (line 17) | type Error struct
method release (line 29) | func (e *Error) release() error {
method Error (line 46) | func (e *Error) Error() string {
method Normalize (line 69) | func (e *Error) Normalize() {
function newError (line 23) | func newError(kind, val *Base, tb *C.PyObject) *Error {
function NewErrorV (line 81) | func NewErrorV(kind *Base, value *Base) *Error {
function NewError (line 89) | func NewError(kind *Base, format string, args ...interface{}) *Error {
function Raise (line 96) | func Raise(err error) {
function GetException (line 113) | func GetException() error {
function exceptionRaised (line 117) | func exceptionRaised() bool {
function exception (line 121) | func exception() error {
function ssize_t2Int64Err (line 132) | func ssize_t2Int64Err(s C.Py_ssize_t) (int64, error) {
function int2BoolErr (line 139) | func int2BoolErr(i C.int) (bool, error) {
function int2Err (line 146) | func int2Err(i C.int) error {
function obj2ObjErr (line 153) | func obj2ObjErr(obj *C.PyObject) (*Base, error) {
FILE: examples/gomodule/gomodule.go
type FooModule (line 11) | type FooModule struct
method Py_bar (line 14) | func (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {
method Py_bar2 (line 25) | func (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {
constant pyCode (line 38) | pyCode = `
function main (line 45) | func main() {
FILE: exception.go
type ExceptionClass (line 7) | type ExceptionClass struct
method ErrV (line 17) | func (kind *ExceptionClass) ErrV(obj *Base) *Error {
method Err (line 23) | func (kind *ExceptionClass) Err(format string, args ...interface{}) *E...
function newException (line 12) | func newException(obj *C.PyObject) *ExceptionClass {
FILE: float.go
type Float (line 8) | type Float struct
method Float (line 37) | func (f *Float) Float() float64 {
function newFloat (line 17) | func newFloat(obj *C.PyObject) *Float {
function NewFloat (line 21) | func NewFloat(i float64) *Float {
function AsFloat (line 25) | func AsFloat(o *Base) (v *Float, ok bool) {
function NewFloatFromString (line 32) | func NewFloatFromString(s string) *Float {
FILE: goargs.go
function ToInt (line 12) | func ToInt(in *Base) (int, bool) {
function ToLong (line 18) | func ToLong(in *Base) (int64, bool) {
function ToString (line 29) | func ToString(in *Base) (string, bool) {
function ToInterface (line 37) | func ToInterface(in *Base) (v interface{}, ok bool) {
function assignToMap (line 49) | func assignToMap(in *Base, out reflect.Value) (err error) {
function assignToComplex (line 87) | func assignToComplex(in *Base, out1 reflect.Value) (err error) {
function AssignTo (line 105) | func AssignTo(in *Base, out interface{}) (err error) {
function Parse (line 129) | func Parse(in *Tuple, out ...interface{}) (err error) {
function ParseV (line 152) | func ParseV(in *Tuple, out ...interface{}) (err error) {
FILE: gofunction.c
function setMethod (line 4) | int setMethod(PyMethodDef* d, int nin) {
FILE: gofunction.go
type Closure (line 13) | type Closure struct
method NewFunction (line 19) | func (closure *Closure) NewFunction(name string, nin int, doc string) ...
function goClassCallMethodArgs (line 42) | func goClassCallMethodArgs(obj, args unsafe.Pointer) unsafe.Pointer {
function goClassCallMethodKwds (line 66) | func goClassCallMethodKwds(obj, args, kwds unsafe.Pointer) unsafe.Pointer {
FILE: gomodule.go
type GoModule (line 10) | type GoModule struct
function NewGoModule (line 15) | func NewGoModule(name string, doc string, self interface{}) (mod GoModul...
FILE: gomodule_test.go
type FooModule (line 10) | type FooModule struct
method Py_bar (line 13) | func (r *FooModule) Py_bar(args *Tuple) (ret *Base, err error) {
type gomoduleCase (line 26) | type gomoduleCase struct
function TestGoModule (line 38) | func TestGoModule(t *testing.T) {
FILE: goregister.go
function sigMatches (line 11) | func sigMatches(got, want reflect.Type) bool {
type RegisterCtx (line 43) | type RegisterCtx
function Register (line 45) | func Register(dict *Dict, nsprefix string, self interface{}) (ctx Regist...
FILE: goregister_test.go
function init (line 8) | func init() {
type Foo (line 14) | type Foo struct
method Py_foo (line 17) | func (r *Foo) Py_foo(args *Tuple) (*Base, error) {
method Py_bar (line 21) | func (r *Foo) Py_bar(args *Tuple) (*Base) {
function _TestRegister (line 27) | func _TestRegister(t *testing.T) {
FILE: int.go
type Int (line 12) | type Int struct
method Int (line 40) | func (i *Int) Int() int {
function newInt (line 21) | func newInt(obj *C.PyObject) *Int {
function NewInt (line 25) | func NewInt(i int) *Int {
function NewInt64 (line 29) | func NewInt64(i int64) *Int {
function AsInt (line 33) | func AsInt(o *Base) (v *Int, ok bool) {
FILE: long.go
type Long (line 8) | type Long struct
method Long (line 32) | func (l *Long) Long() int64 {
function newLong (line 17) | func newLong(obj *C.PyObject) *Long {
function NewLong (line 21) | func NewLong(i int64) *Long {
function AsLong (line 25) | func AsLong(o *Base) (v *Long, ok bool) {
FILE: module.go
type Module (line 10) | type Module struct
method CheckExact (line 66) | func (mod *Module) CheckExact() bool {
method Dict (line 71) | func (mod *Module) Dict() *Dict {
method Name (line 78) | func (mod *Module) Name() (string, error) {
method Filename (line 86) | func (mod *Module) Filename() (string, error) {
method AddObject (line 94) | func (mod *Module) AddObject(name string, obj *Base) error {
method AddIntConstant (line 110) | func (mod *Module) AddIntConstant(name string, value int) error {
method AddStringConstant (line 122) | func (mod *Module) AddStringConstant(name, value string) error {
function newModule (line 18) | func newModule(obj *C.PyObject) *Module {
function Import (line 22) | func Import(name string) (*Module, error) {
function ExecCodeModule (line 37) | func ExecCodeModule(name string, code *Base) (*Module, error) {
function NewModule (line 47) | func NewModule(name string) (*Module, error) {
function AsModule (line 59) | func AsModule(o *Base) (v *Module, ok bool) {
FILE: module_test.go
type moduleCase (line 7) | type moduleCase struct
function TestModule (line 22) | func TestModule(t *testing.T) {
FILE: none.go
function IncNone (line 12) | func IncNone() *Base {
FILE: number.go
type NumberProtocol (line 14) | type NumberProtocol struct
method Add (line 24) | func (n *NumberProtocol) Add(obj *Base) (*Base, error) {
method Subtract (line 33) | func (n *NumberProtocol) Subtract(obj *Base) (*Base, error) {
method Multiply (line 42) | func (n *NumberProtocol) Multiply(obj *Base) (*Base, error) {
method Divide (line 51) | func (n *NumberProtocol) Divide(obj *Base) (*Base, error) {
method FloorDivide (line 59) | func (n *NumberProtocol) FloorDivide(obj *Base) (*Base, error) {
method TrueDivide (line 67) | func (n *NumberProtocol) TrueDivide(obj *Base) (*Base, error) {
method Remainder (line 76) | func (n *NumberProtocol) Remainder(obj *Base) (*Base, error) {
method Divmod (line 84) | func (n *NumberProtocol) Divmod(obj *Base) (*Base, error) {
method Power (line 92) | func (n *NumberProtocol) Power(obj1, obj2 *Base) (*Base, error) {
method Negative (line 100) | func (n *NumberProtocol) Negative() (*Base, error) {
method Positive (line 108) | func (n *NumberProtocol) Positive() (*Base, error) {
method Absolute (line 116) | func (n *NumberProtocol) Absolute() (*Base, error) {
method Invert (line 124) | func (n *NumberProtocol) Invert() (*Base, error) {
method Lshift (line 133) | func (n *NumberProtocol) Lshift(obj *Base) (*Base, error) {
method Rshift (line 142) | func (n *NumberProtocol) Rshift(obj *Base) (*Base, error) {
method And (line 151) | func (n *NumberProtocol) And(obj *Base) (*Base, error) {
method Xor (line 160) | func (n *NumberProtocol) Xor(obj *Base) (*Base, error) {
method Or (line 168) | func (n *NumberProtocol) Or(obj *Base) (*Base, error) {
method InPlaceAdd (line 177) | func (n *NumberProtocol) InPlaceAdd(obj *Base) (*Base, error) {
method InPlaceSubtract (line 186) | func (n *NumberProtocol) InPlaceSubtract(obj *Base) (*Base, error) {
method InPlaceMultiply (line 195) | func (n *NumberProtocol) InPlaceMultiply(obj *Base) (*Base, error) {
method InPlaceDivide (line 204) | func (n *NumberProtocol) InPlaceDivide(obj *Base) (*Base, error) {
method InPlaceFloorDivide (line 212) | func (n *NumberProtocol) InPlaceFloorDivide(obj *Base) (*Base, error) {
method InPlaceTrueDivide (line 220) | func (n *NumberProtocol) InPlaceTrueDivide(obj *Base) (*Base, error) {
method InPlaceRemainder (line 229) | func (n *NumberProtocol) InPlaceRemainder(obj *Base) (*Base, error) {
method InPlacePower (line 240) | func (n *NumberProtocol) InPlacePower(obj1, obj2 *Base) (*Base, error) {
method InPlaceLshift (line 249) | func (n *NumberProtocol) InPlaceLshift(obj *Base) (*Base, error) {
method InPlaceRshift (line 258) | func (n *NumberProtocol) InPlaceRshift(obj *Base) (*Base, error) {
method InPlaceAnd (line 267) | func (n *NumberProtocol) InPlaceAnd(obj *Base) (*Base, error) {
method InPlaceXor (line 276) | func (n *NumberProtocol) InPlaceXor(obj *Base) (*Base, error) {
method InPlaceOr (line 285) | func (n *NumberProtocol) InPlaceOr(obj *Base) (*Base, error) {
function cnp (line 16) | func cnp(n *NumberProtocol) *C.PyObject {
FILE: object.go
type Op (line 9) | type Op
constant LT (line 12) | LT = Op(C.Py_LT)
constant LE (line 13) | LE = Op(C.Py_LE)
constant EQ (line 14) | EQ = Op(C.Py_EQ)
constant NE (line 15) | NE = Op(C.Py_NE)
constant GT (line 16) | GT = Op(C.Py_GT)
constant GE (line 17) | GE = Op(C.Py_GE)
type Base (line 22) | type Base struct
method c (line 28) | func (obj *Base) c() *C.PyObject {
method Obj (line 32) | func (obj *Base) Obj() *Base {
method Init (line 38) | func (obj *Base) Init(args *Tuple, kw *Dict) error {
method Type (line 44) | func (obj *Base) Type() *Type {
method Decref (line 50) | func (obj *Base) Decref() {
method Incref (line 55) | func (obj *Base) Incref() {
method IsTrue (line 61) | func (obj *Base) IsTrue() bool {
method Not (line 71) | func (obj *Base) Not() bool {
method HasAttr (line 81) | func (obj *Base) HasAttr(name *Base) bool {
method HasAttrString (line 91) | func (obj *Base) HasAttrString(name string) bool {
method GetAttr (line 105) | func (obj *Base) GetAttr(name *Base) (*Base, error) {
method GetAttrString (line 114) | func (obj *Base) GetAttrString(name string) (*Base, error) {
method SetAttr (line 126) | func (obj *Base) SetAttr(name, value *Base) error {
method SetAttrString (line 133) | func (obj *Base) SetAttrString(name string, value *Base) error {
method DelAttr (line 145) | func (obj *Base) DelAttr(name *Base) error {
method DelAttrString (line 152) | func (obj *Base) DelAttrString(name string) error {
method RichCompare (line 164) | func (obj *Base) RichCompare(obj2 *Base, op Op) (*Base, error) {
method RichCompareBool (line 172) | func (obj *Base) RichCompareBool(obj2 *Base, op Op) (bool, error) {
method Compare (line 182) | func (obj *Base) Compare(obj2 *Base) (int, error) {
method Repr (line 191) | func (obj *Base) Repr() (*Base, error) {
method Str (line 200) | func (obj *Base) Str() (*Base, error) {
method String (line 205) | func (obj *Base) String() string {
method Bytes (line 221) | func (obj *Base) Bytes() (*Base, error) {
method IsInstance (line 233) | func (obj *Base) IsInstance(cls *Base) (bool, error) {
method IsSubclass (line 241) | func (obj *Base) IsSubclass(cls *Base) (bool, error) {
method Call (line 252) | func (obj *Base) Call(args *Tuple, kwds *Dict) (*Base, error) {
method CallObject (line 262) | func (obj *Base) CallObject(args *Tuple) (*Base, error) {
method CallMethodObject (line 271) | func (obj *Base) CallMethodObject(name string, args *Tuple) (*Base, er...
method CallObjArgs (line 289) | func (obj *Base) CallObjArgs(args ...*Base) (*Base, error) {
method CallMethodObjArgs (line 295) | func (obj *Base) CallMethodObjArgs(name string, args ...*Base) (*Base,...
method Length (line 308) | func (obj *Base) Length() (int64, error) {
method Size (line 315) | func (obj *Base) Size() (int64, error) {
method GetItem (line 324) | func (obj *Base) GetItem(key *Base) (*Base, error) {
method SetItem (line 331) | func (obj *Base) SetItem(key, value *Base) error {
method DelItem (line 338) | func (obj *Base) DelItem(key *Base) error {
method Dir (line 345) | func (obj *Base) Dir() (*Base, error) {
function newObject (line 24) | func newObject(obj *C.PyObject) *Base {
FILE: object_test.go
function TestBase (line 7) | func TestBase(t *testing.T) {
FILE: python.go
function init (line 19) | func init() {
function Initialize (line 23) | func Initialize() {
function InitializeEx (line 27) | func InitializeEx(initsigs bool) {
function Finalize (line 35) | func Finalize() {
function AddToPath (line 39) | func AddToPath(dir string) {
function Main (line 59) | func Main(args []string) int {
function EnterRecursiveCall (line 77) | func EnterRecursiveCall(where string) bool {
function LeaveRecursiveCall (line 85) | func LeaveRecursiveCall() {
FILE: pyutil/call.go
function PackEx (line 11) | func PackEx(cfg *Config, args ...interface{}) (ret *py.Tuple, err error) {
function Pack (line 27) | func Pack(args ...interface{}) (ret *py.Tuple, err error) {
function CallEx (line 34) | func CallEx(cfg *Config, fn *py.Base, args ...interface{}) (ret *py.Base...
function Call (line 46) | func Call(fn *py.Base, args ...interface{}) (*py.Base, error) {
function CallMethodEx (line 53) | func CallMethodEx(cfg *Config, self *py.Base, method string, args ...int...
function CallMethod (line 65) | func CallMethod(self *py.Base, method string, args ...interface{}) (ret ...
function NewInstanceEx (line 72) | func NewInstanceEx(cfg *Config, typ *py.Class, args ...interface{}) (ret...
function NewInstance (line 84) | func NewInstance(typ *py.Class, args ...interface{}) (ret *py.Base, err ...
function NewEx (line 91) | func NewEx(cfg *Config, mod *py.Base, clsname string, args ...interface{...
function New (line 109) | func New(mod *py.Base, clsname string, args ...interface{}) (ret *py.Bas...
FILE: pyutil/call_test.go
type moduleCase (line 10) | type moduleCase struct
function TestCall (line 23) | func TestCall(t *testing.T) {
FILE: pyutil/var.go
type Config (line 11) | type Config struct
function tagName (line 22) | func tagName(tag string) (string) {
function newStruct (line 29) | func newStruct(sv reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
function newMap (line 54) | func newMap(v reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
function newComplex (line 79) | func newComplex(val reflect.Value, cfg *Config) (ret *py.Base, ok bool) {
function NewVarEx (line 96) | func NewVarEx(val interface{}, cfg *Config) (ret *py.Base, ok bool) {
function NewVar (line 109) | func NewVar(val interface{}) (ret *py.Base, ok bool) {
FILE: pyutil/var_test.go
type Foo (line 8) | type Foo struct
function Test (line 13) | func Test(t *testing.T) {
function checkFoo (line 68) | func checkFoo(val *py.Dict, t *testing.T) bool {
FILE: string.go
type String (line 8) | type String struct
method String (line 34) | func (s *String) String() string {
method Format (line 42) | func (s *String) Format(args *Tuple) (*String, error) {
function newString (line 16) | func newString(obj *C.PyObject) *String {
function NewString (line 20) | func NewString(s string) *String {
function AsString (line 27) | func AsString(o *Base) (v *String, ok bool) {
FILE: tuple.go
type Tuple (line 10) | type Tuple struct
method CheckExact (line 68) | func (t *Tuple) CheckExact() bool {
method Size (line 76) | func (t *Tuple) Size() int {
method GetItem (line 88) | func (t *Tuple) GetItem(pos int) (*Base, error) {
method GetSlice (line 93) | func (t *Tuple) GetSlice(low, high int) (*Tuple, error) {
method SetItem (line 103) | func (t *Tuple) SetItem(pos int, obj *Base) error {
method Slice (line 112) | func (t *Tuple) Slice() []*Base {
function newTuple (line 18) | func newTuple(obj *C.PyObject) *Tuple {
function NewTuple (line 27) | func NewTuple(size int) *Tuple {
function AsTuple (line 32) | func AsTuple(o *Base) (v *Tuple, ok bool) {
function PackTuple (line 43) | func PackTuple(items ...*Base) *Tuple {
FILE: type.go
type Type (line 18) | type Type struct
method NewNoArgs (line 37) | func (t *Type) NewNoArgs() (ret *Base, err error) {
method New (line 43) | func (t *Type) New(args *Tuple, kw *Dict) (ret *Base, err error) {
method NewObjArgs (line 48) | func (t *Type) NewObjArgs(args ...*Base) (ret *Base, err error) {
method Alloc (line 54) | func (t *Type) Alloc(n int64) (*Base, error) {
method Init (line 59) | func (t *Type) Init(obj *Base, args *Tuple, kw *Dict) error {
method CheckExact (line 69) | func (t *Type) CheckExact() bool {
method Modified (line 77) | func (t *Type) Modified() {
method HasFeature (line 82) | func (t *Type) HasFeature(feature uint32) bool {
method IsGc (line 87) | func (t *Type) IsGc() bool {
method IsSubtype (line 92) | func (t *Type) IsSubtype(t2 *Type) bool {
function newType (line 26) | func newType(obj *C.PyObject) *Type {
function AsType (line 30) | func AsType(o *Base) (v *Type, ok bool) {
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (90K chars).
[
{
"path": ".gitignore",
"chars": 258,
"preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n*.pyc\n\n# Folders\n_obj\n_test\n\n# Architectu"
},
{
"path": "CHANGELOG.md",
"chars": 272,
"preview": "#CHANGELOG\n\n## v1.1.00\n\n2013-05-28 Issue [#17](https://github.com/qiniu/py/pull/17):\n\n- bugfix: Closure add methodDef to"
},
{
"path": "LICENSE",
"chars": 1036,
"preview": "MIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associate"
},
{
"path": "README.md",
"chars": 1633,
"preview": "py - Golang bindings to the CPython C-API\n==\n\n**NOTE**: This project is **unmaintained**. Maybe [https://github.com/go-p"
},
{
"path": "class.go",
"chars": 1292,
"preview": "package py\n\n// #include <Python.h>\n// static inline int classCheck(PyObject *o) { return PyClass_Check(o); }\nimport \"C\"\n"
},
{
"path": "code.go",
"chars": 3793,
"preview": "package py\n\n/*\n#include <Python.h>\n\nstatic inline int codeCheck(PyObject *o) { return PyCode_Check(o); }\nstatic inline v"
},
{
"path": "code_test.go",
"chars": 1676,
"preview": "package py\n\nimport (\n\t\"testing\"\n)\n\ntype compileCase struct {\n\texp string\n\tret string\n\tstart StartToken\n}\n\nvar g_compileC"
},
{
"path": "dict.go",
"chars": 7903,
"preview": "package py\n\n// #include <Python.h>\n// static inline int dictCheck(PyObject *o) { return PyDict_Check(o); }\n// static inl"
},
{
"path": "error.go",
"chars": 3723,
"preview": "package py\n\n// #include <Python.h>\n// static inline void incref(PyObject *obj) { Py_INCREF(obj); }\n// static inline void"
},
{
"path": "examples/gomodule/gomodule.go",
"chars": 1272,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/qiniu/log\"\n\t\"github.com/qiniu/py\"\n)\n\n// -------------------------------------"
},
{
"path": "exc.go",
"chars": 3312,
"preview": "package py\n\n// #include <Python.h>\nimport \"C\"\n\nvar (\n\tBaseException = newException(C.PyExc_BaseException)\n\tE"
},
{
"path": "exception.go",
"chars": 672,
"preview": "package py\n\n// #include <Python.h>\nimport \"C\"\nimport \"unsafe\"\n\ntype ExceptionClass struct {\n\tBase\n\to C.PyBaseExceptionOb"
},
{
"path": "float.go",
"chars": 846,
"preview": "package py\n\n// #include <Python.h>\n// static inline double floatCheck(PyObject *o) { return PyFloat_Check(o); }\nimport \""
},
{
"path": "goargs.go",
"chars": 4491,
"preview": "package py\n\nimport (\n\t\"reflect\"\n\t\"syscall\"\n\t\"github.com/qiniu/log\"\n\t\"github.com/qiniu/errors\"\n)\n\n// --------------------"
},
{
"path": "gofunction.c",
"chars": 357,
"preview": "#include <Python.h>\n#include \"_cgo_export.h\"\n\nint setMethod(PyMethodDef* d, int nin) {\n\tswitch (nin) {\n\tcase 3:\n\t\td->ml_"
},
{
"path": "gofunction.go",
"chars": 2049,
"preview": "package py\n\n/*\n#include <Python.h>\n#include \"gofunction.h\"\n\nstatic inline void decref(PyObject *obj) { Py_DECREF(obj); }"
},
{
"path": "gofunction.h",
"chars": 137,
"preview": "#ifndef QBOX_GOPY_GOFUNCTION_H\n#define QBOX_GOPY_GOFUNCTION_H\n\nint setMethod(PyMethodDef* d, int nin);\n\n#endif /* _GO_PY"
},
{
"path": "gomodule.go",
"chars": 848,
"preview": "package py\n\n// #include <Python.h>\n// static inline void decref(PyObject *obj) { Py_DECREF(obj); }\nimport \"C\"\nimport \"un"
},
{
"path": "gomodule_test.go",
"chars": 1181,
"preview": "package py\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\n// ---------------------------------------------------------------------------"
},
{
"path": "goregister.go",
"chars": 1963,
"preview": "package py\n\nimport \"reflect\"\nimport \"strings\"\nimport \"github.com/qiniu/log\"\n\n// ----------------------------------------"
},
{
"path": "goregister_test.go",
"chars": 657,
"preview": "package py\n\nimport (\n\t\"testing\"\n\t\"github.com/qiniu/log\"\n)\n\nfunc init() {\n\tlog.SetOutputLevel(0)\n}\n\n// ------------------"
},
{
"path": "int.go",
"chars": 879,
"preview": "// Copyright 2011 Julian Phillips. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// licens"
},
{
"path": "long.go",
"chars": 672,
"preview": "package py\n\n// #include <Python.h>\n// static inline long longCheck(PyObject *o) { return PyLong_Check(o); }\nimport \"C\"\ni"
},
{
"path": "module.go",
"chars": 2943,
"preview": "package py\n\n// #include <Python.h>\n// static inline int moduleCheck(PyObject *o) { return PyModule_Check(o); }\n// static"
},
{
"path": "module_test.go",
"chars": 1267,
"preview": "package py\n\nimport (\n\t\"testing\"\n)\n\ntype moduleCase struct {\n\texp string\n\tname, ret, globals string\n}\n\nvar g_moduleCases "
},
{
"path": "none.go",
"chars": 352,
"preview": "package py\n\n/*\n#include <Python.h>\n\nstatic inline PyObject* incNone() { Py_RETURN_NONE; }\n*/\nimport \"C\"\n\n// ------------"
},
{
"path": "number.go",
"chars": 9153,
"preview": "// Copyright 2011 Julian Phillips. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// licens"
},
{
"path": "object.go",
"chars": 10428,
"preview": "package py\n\n// #include <Python.h>\n// static inline void incref(PyObject *obj) { Py_INCREF(obj); }\n// static inline void"
},
{
"path": "object_test.go",
"chars": 769,
"preview": "package py\n\nimport (\n\t\"testing\"\n)\n\nfunc TestBase(t *testing.T) {\n\n\t{\n\t\tv := NewString(\"Hello!\")\n\t\tdefer v.Decref()\n\n\t\tif"
},
{
"path": "python.go",
"chars": 1787,
"preview": "package py\n\n/*\n#cgo pkg-config: python-2.7\n\n#include <Python.h>\n\nstatic inline int enterRecursive(char *w) {\n\treturn Py_"
},
{
"path": "pyutil/call.go",
"chars": 2935,
"preview": "package pyutil\n\nimport (\n\t\"syscall\"\n\t\"github.com/qiniu/py\"\n\t\"github.com/qiniu/errors\"\n)\n\n// ----------------------------"
},
{
"path": "pyutil/call_test.go",
"chars": 1145,
"preview": "package pyutil\n\nimport (\n\t\"testing\"\n\t\"github.com/qiniu/log\"\n\t\"github.com/qiniu/errors\"\n\t\"github.com/qiniu/py\"\n)\n\ntype mo"
},
{
"path": "pyutil/var.go",
"chars": 2288,
"preview": "package pyutil\n\nimport (\n\t\"strings\"\n\t\"reflect\"\n\t\"github.com/qiniu/py\"\n)\n\n// --------------------------------------------"
},
{
"path": "pyutil/var_test.go",
"chars": 1548,
"preview": "package pyutil\n\nimport (\n\t\"testing\"\n\t\"github.com/qiniu/py\"\n)\n\ntype Foo struct {\n\tA\tint\t\t`json:\"a\"`\n\tB\tstring\t`json:\"b\"`\n"
},
{
"path": "string.go",
"chars": 979,
"preview": "package py\n\n// #include <Python.h>\n// static inline int stringCheck(PyObject *o) { return PyString_Check(o); }\nimport \"C"
},
{
"path": "tuple.go",
"chars": 3353,
"preview": "package py\n\n// #include <Python.h>\n// static inline int tupleCheckE(PyObject *o) { return PyTuple_CheckExact(o); }\n// st"
},
{
"path": "type.go",
"chars": 2796,
"preview": "package py\n\n// #include <Python.h>\n// static inline int typeCheck(PyObject *o) { return PyType_Check(o); }\n// static inl"
}
]
About this extraction
This page contains the full source code of the qiniu/py GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (80.7 KB), approximately 23.3k tokens, and a symbol index with 273 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.