[
  {
    "path": ".gitignore",
    "content": "# 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# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "#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 fix that gc recycle methodDef\n- 支持 Float 类型\n\n\n## v1.0.01\n\n2013-03-10 Issue [#5](https://github.com/qiniu/py/pull/5):\n\n- 增加 gomodule 样例\n- Travis-CI 支持\n\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "py - Golang bindings to the CPython C-API\n==\n\n**NOTE**: This project is **unmaintained**. Maybe [https://github.com/go-python/cpy3](https://github.com/go-python/cpy3) is a good replacement.\n\npy is Golang bindings to the CPython C-API.\n\npy project's homepage is: https://github.com/qiniu/py\n\n# Install\n\n```\ngo get github.com/qiniu/py\n```\n\n# Example\n\n```{go}\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/qiniu/log\"\n\t\"github.com/qiniu/py\"\n)\n\n// -------------------------------------------------------------------\n\ntype FooModule struct {\n}\n\nfunc (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {\n\tvar i int\n\tvar s string\n\terr = py.Parse(args, &i, &s)\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(\"call foo.bar:\", i, s)\n\treturn py.IncNone(), nil\n}\n\nfunc (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {\n\tvar i int\n\tvar s []string\n\terr = py.ParseV(args, &i, &s)\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(\"call foo.bar2:\", i, s)\n\treturn py.IncNone(), nil\n}\n\n// -------------------------------------------------------------------\n\nconst pyCode = `\n\nimport foo\nfoo.bar(1, 'Hello')\nfoo.bar2(1, 'Hello', 'world!')\n`\n\nfunc main() {\n\n\tgomod, err := py.NewGoModule(\"foo\", \"\", new(FooModule))\n\tif err != nil {\n\t\tlog.Fatal(\"NewGoModule failed:\", err)\n\t}\n\tdefer gomod.Decref()\n\n\tcode, err := py.Compile(pyCode, \"\", py.FileInput)\n\tif err != nil {\n\t\tlog.Fatal(\"Compile failed:\", err)\n\t}\n\tdefer code.Decref()\n\n\tmod, err := py.ExecCodeModule(\"test\", code.Obj())\n\tif err != nil {\n\t\tlog.Fatal(\"ExecCodeModule failed:\", err)\n\t}\n\tdefer mod.Decref()\n}\n\n// -------------------------------------------------------------------\n```\n\n"
  },
  {
    "path": "class.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int classCheck(PyObject *o) { return PyClass_Check(o); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Class struct {\n\tBase\n\to C.PyClassObject\n}\n\n// ClassType is the Type object that represents the Class type.\nvar ClassType = (*Type)(unsafe.Pointer(&C.PyClass_Type))\n\nfunc newClass(obj *C.PyObject) *Class {\n\treturn (*Class)(unsafe.Pointer(obj))\n}\n\nfunc AsClass(o *Base) (v *Class, ok bool) {\n\tif ok = C.classCheck(o.c()) != 0; ok {\n\t\tv = newClass(o.c())\n\t}\n\treturn\n}\n\nfunc (t *Class) NewNoArgs() (ret *Base, err error) {\n\targs := NewTuple(0)\n\tdefer args.Decref()\n\treturn t.New(args, nil)\n}\n\n// Return value: New reference.\n// Create a new instance of a specific class. The parameters arg and kw are used as \n// the positional and keyword parameters to the object’s constructor.\nfunc (t *Class) New(args *Tuple, kw *Dict) (ret *Base, err error) {\n\tret1 := C.PyInstance_New(t.c(), args.c(), kw.c())\n\treturn obj2ObjErr(ret1)\n}\n\nfunc (t *Class) NewObjArgs(args ...*Base) (ret *Base, err error) {\n\targs1 := PackTuple(args...)\n\tdefer args1.Decref()\n\treturn t.New(args1, nil)\n}\n\n// Return true if klass is a subclass of base. Return false in all other cases.\nfunc (t *Class) IsSubclass(base *Base) bool {\n\treturn C.PyClass_IsSubclass(t.c(), base.c()) != 0\n}\n\n"
  },
  {
    "path": "code.go",
    "content": "package py\n\n/*\n#include <Python.h>\n\nstatic inline int codeCheck(PyObject *o) { return PyCode_Check(o); }\nstatic inline void decref(PyObject *obj) { Py_DECREF(obj); }\n\nstatic inline FILE* openFile(char* name) {\n\treturn fopen(name, \"r\");\n}\n\nstatic inline PyObject* compileString(char* text, char* filename, int start) {\n\treturn Py_CompileString(text, filename, start);\n}\n\nstatic PyObject* compileFile(FILE* f, char* name, int start) {\n\tstruct _node *n = PyParser_SimpleParseFile(f, name, start);\n\tif (!n) return NULL;\n\treturn (PyObject*)PyNode_Compile(n, name);\n}\n*/\nimport \"C\"\nimport \"unsafe\"\n\n// ------------------------------------------------------------------------------------------\n// type StartToken\n\ntype StartToken int\n\nconst (\n\tEvalInput = StartToken(C.Py_eval_input)\t// for isolated expressions\n\n\tFileInput = StartToken(C.Py_file_input) // for sequences of statements as read from a file or other source;\n\t\t\t\t\t\t\t\t\t\t\t// to use when compiling arbitrarily long Python source code.\n\n\tSingleInput = StartToken(C.Py_single_input) // for a single statement; used for the interactive interpreter loop.\n)\n\n// ------------------------------------------------------------------------------------------\n// type Code\n\ntype Code struct {\n\tBase\n\to C.PyCodeObject\n}\n\n// CodeType is the Type object that represents the Code type.\nvar CodeType = (*Type)(unsafe.Pointer(&C.PyCode_Type))\n\nfunc newCode(obj *C.PyObject) *Code {\n\treturn (*Code)(unsafe.Pointer(obj))\n}\n\nfunc AsCode(o *Base) (v *Code, ok bool) {\n\tif ok = C.codeCheck(o.c()) != 0; ok {\n\t\tv = newCode(o.c())\n\t}\n\treturn\n}\n\nfunc Compile(text, filename string, start StartToken) (*Code, error) {\n\tt := C.CString(text)\n\tdefer C.free(unsafe.Pointer(t))\n\n\tfn := C.CString(filename)\n\tdefer C.free(unsafe.Pointer(fn))\n\n\tret := C.compileString(t, fn, C.int(start))\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newCode(ret), nil\n}\n\nfunc CompileFile(name string, start StartToken) (*Code, error) {\n\tfn := C.CString(name)\n\tdefer C.free(unsafe.Pointer(fn))\n\n\tfile, err := C.openFile(fn)\n\tif file == nil {\n\t\treturn nil, err\n\t}\n\tdefer C.fclose(file)\n\n\tret := C.compileFile(file, fn, C.int(start))\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newCode(ret), nil\n}\n\n// Return value: New reference.\nfunc (code *Code) Eval(globals, locals *Base) (*Base, error) {\n\tpyCode := (*C.PyCodeObject)(unsafe.Pointer(code))\n\tret := C.PyEval_EvalCode(pyCode, globals.c(), locals.c())\n\treturn obj2ObjErr(ret)\n}\n\nfunc (code *Code) Run(globals, locals *Base) error {\n\tpyCode := (*C.PyCodeObject)(unsafe.Pointer(code))\n\tret := C.PyEval_EvalCode(pyCode, globals.c(), locals.c())\n\tif ret == nil {\n\t\treturn exception()\n\t}\n\tC.decref(ret)\n\treturn nil\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc Run(text string) error {\n\n\tt := C.CString(text)\n\tdefer C.free(unsafe.Pointer(t))\n\t\n\tret := C.PyRun_SimpleStringFlags(t, nil)\n\treturn int2Err(ret)\n}\n\n// Return a dictionary of the builtins in the current execution frame, or the interpreter of \n// the thread state if no frame is currently executing.\n//\n// Return value: Borrowed reference.\nfunc GetBuiltins() *Base {\n\tret := C.PyEval_GetBuiltins()\n\treturn newObject(ret)\n}\n\n// Return a dictionary of the global variables in the current execution frame,\n// or NULL if no frame is currently executing.\n//\n// Return value: Borrowed reference\nfunc GetLocals() *Base {\n\tret := C.PyEval_GetLocals()\n\treturn newObject(ret)\n}\n\n// Return a dictionary of the local variables in the current execution frame, \n// or NULL if no frame is currently executing.\n//\n// Return value: Borrowed reference\nfunc GetGlobals() *Base {\n\tret := C.PyEval_GetGlobals()\n\treturn newObject(ret)\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "code_test.go",
    "content": "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_compileCases = []compileCase{\n\t{\"1+2\", \"3\", EvalInput},\n\t{\"1+2\", \"None\", SingleInput}, // echo\n\t{\"1+2\", \"None\", FileInput},\n}\n\nfunc TestCompile(t *testing.T) {\n\n\tfor _, c := range g_compileCases {\n\t\tcode, err := Compile(c.exp, \"\", c.start)\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Compile failed:\", err)\n\t\t}\n\t\tdefer code.Decref()\n\n\t\tglobals := NewDict()\n\t\tdefer globals.Decref()\n\n\t\tlocals := NewDict()\n\t\tdefer locals.Decref()\n\n\t\tret, err := code.Eval(globals.Obj(), locals.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Eval failed:\", err)\n\t\t}\n\t\tdefer ret.Decref()\n\n\t\tif ret.String() != c.ret {\n\t\t\tt.Fatal(\"Eval ret:\", ret.String())\n\t\t}\n\t}\n}\n\ntype evalLocalGlobalsCase struct {\n\texp string\n\tglobals string\n\tlocals string\n\tstart StartToken\n}\n\nvar g_evalLocalGlobalsCases = []evalLocalGlobalsCase{\n\t{\"v=1+2\", \"{}\", \"{'v': 3}\", FileInput},\n\t{\"v=1+2\", \"{}\", \"{'v': 3}\", SingleInput}, // echo\n//\t{\"v=1+2\", \"{}\", \"{'v': 3}\", EvalInput}, // compile error\n}\n\nfunc _TestEvalLocalGlobals(t *testing.T) {\n\n\tInitialize()\n\tdefer Finalize()\n\n\tfor _, c := range g_evalLocalGlobalsCases {\n\t\tcode, err := Compile(c.exp, \"\", c.start)\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Compile failed:\", c.exp, c.start, err)\n\t\t}\n\t\tdefer code.Decref()\n\n\t\tglobals := NewDict()\n\t\tdefer globals.Decref()\n\n\t\tlocals := NewDict()\n\t\tdefer locals.Decref()\n\n\t\terr = code.Run(globals.Obj(), locals.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Run failed:\", err)\n\t\t}\n\t\tprintln(globals.String(), locals.String())\n\n\t\tif locals.String() != c.locals || globals.String() != c.globals {\n\t\t\tt.Fatal(\"Run:\", globals.String(), locals.String())\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "dict.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int dictCheck(PyObject *o) { return PyDict_Check(o); }\n// static inline int dictCheckE(PyObject *o) { return PyDict_CheckExact(o); }\nimport \"C\"\nimport \"unsafe\"\n\n// *Dict represents a Python dictionary.  In addition to satisfying the Object\n// interface, Dict pointers also have a number of methods defined - representing\n// the PyDict_XXX functions from the Python C API.\ntype Dict struct {\n\tBase\n\to C.PyDictObject\n}\n\n// DictType is the Type object that represents the Dict type.\nvar DictType = (*Type)(unsafe.Pointer(&C.PyDict_Type))\n\nfunc newDict(obj *C.PyObject) *Dict {\n\treturn (*Dict)(unsafe.Pointer(obj))\n}\n\n// NewDict creates a new empty dictionary.\n//\n// Return value: New Reference.\nfunc NewDict() *Dict {\n\tret := C.PyDict_New()\n\treturn newDict(ret)\n}\n\nfunc NewDictProxy(obj *Base) *Dict {\n\tret := C.PyDictProxy_New(obj.c())\n\treturn newDict(ret)\n}\n\nfunc AsDict(o *Base) (v *Dict, ok bool) {\n\tif ok = C.dictCheck(o.c()) != 0; ok {\n\t\tv = newDict(o.c())\n\t}\n\treturn\n}\n\n// CheckExact returns true if d is an actual dictionary object, and not an\n// instance of a sub type.\nfunc (d *Dict) CheckExact() bool {\n\tret := C.dictCheckE(d.c())\n\tif int(ret) != 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// Clear empties the dictionary d of all key-value pairs.\nfunc (d *Dict) Clear() {\n\tC.PyDict_Clear(d.c())\n}\n\n// Contains Returns true if the dictionary contains the given key.  This is\n// equivalent to the Python expression \"key in d\".\nfunc (d *Dict) Contains(key *Base) (bool, error) {\n\tret := C.PyDict_Contains(d.c(), key.c())\n\treturn int2BoolErr(ret)\n}\n\n// Copy returns a new dictionary that contains the same key-values pairs as d.\n//\n// Return value: New Reference.\nfunc (d *Dict) Copy() (*Base, error) {\n\tret := C.PyDict_Copy(d.c())\n\treturn obj2ObjErr(ret)\n}\n\n// SetItem inserts \"val\" into dictionary d with the key \"key\".  If \"key\" is not\n// hashable, then a TypeError will be returned.\nfunc (d *Dict) SetItem(key, val *Base) error {\n\tret := C.PyDict_SetItem(d.c(), key.c(), val.c())\n\treturn int2Err(ret)\n}\n\n// SetItemString inserts \"val\" into dictionary d with the key \"key\" (or rather,\n// with a *String with the value of \"key\" will be used as the key).  If \"key\" is\n// not hashable, then a TypeError will be returned.\nfunc (d *Dict) SetItemString(key string, val *Base) error {\n\ts := C.CString(key)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyDict_SetItemString(d.c(), s, val.c())\n\treturn int2Err(ret)\n}\n\n// DelItem removes the entry with the key of \"key\" from the dictionary d.  If\n// \"key\" is not hashable, a TypeError is returned.\nfunc (d *Dict) DelItem(key *Base) error {\n\tret := C.PyDict_DelItem(d.c(), key.c())\n\treturn int2Err(ret)\n}\n\n// DelItem removes the entry with the key of \"key\" (or rather, with a *String\n// with the value of \"key\" as the key) from the dictionary d.\nfunc (d *Dict) DelItemString(key string) error {\n\ts := C.CString(key)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyDict_DelItemString(d.c(), s)\n\treturn int2Err(ret)\n}\n\n// GetItem returns the Object from dictionary d which has the key \"key\".  If\n// there is no such Object, then nil is returned (without an error).\n//\n// Return value: Borrowed Reference.\nfunc (d *Dict) GetItem(key *Base) *Base {\n\tret := C.PyDict_GetItem(d.c(), key.c())\n\treturn newObject(ret)\n}\n\n// GetItemString returns the Object from dictionary d which has the key \"key\"\n// (or rather, which has a *String with the value of \"key\" as the key).  If\n// there is no such Object, then nil is returned (without an error).\n//\n// Return value: Borrowed Reference.\nfunc (d *Dict) GetItemString(key string) *Base {\n\ts := C.CString(key)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyDict_GetItemString(d.c(), s)\n\treturn newObject(ret)\n}\n\n/*\n// Items returns a *List containing all the items from the dictionary d, as with\n// the Python \"d.items()\".\n//\n// Return value: New Reference.\nfunc (d *Dict) Items() (*List, error) {\n\tret := C.PyDict_Items(d.c())\n\treturn newList(ret), exception()\n}\n\n// Keys returns a *List containing all the keys from the dictionary d, as with\n// the Python \"d.keys()\".\n//\n// Return value: New Reference.\nfunc (d *Dict) Keys() (*List, error) {\n\tret := C.PyDict_Keys(d.c())\n\treturn newList(ret), exception()\n}\n\n// Values returns a *List containing all the values from the dictionary d, as\n// with the Python \"d.values()\".\n//\n// Return value: New Reference.\nfunc (d *Dict) Values() (*List, error) {\n\tret := C.PyDict_Values(d.c())\n\treturn newList(ret), exception()\n}\n*/\n\n// Size returns the number of items in the dictionary d.  This is equivalent to\n// the Python \"len(d)\".\nfunc (d *Dict) Size() int {\n\tret := C.PyDict_Size(d.c())\n\tif ret < 0 {\n\t\tpanic(exception())\n\t}\n\treturn int(ret)\n}\n\n// PyDict_Next\n\n// Merge merges key values pairs from Object o (which may be a dictionary, or an\n// object that supports \"o.keys()\" and \"o[key]\") into the dictionary d.  If\n// override is true then a matching key in d will have it's value replaced by\n// the one in o, else the value in d will be left.\nfunc (d *Dict) Merge(o *Base, override bool) error {\n\tover := 0\n\tif override {\n\t\tover = 1\n\t}\n\tret := C.PyDict_Merge(d.c(), o.c(), C.int(over))\n\treturn int2Err(ret)\n}\n\n// Update replaces key values pairs in d with those from o.  It is equivalent to\n// d.Merge(o, true) in Go, or \"d.update(o)\" in Python.\nfunc (d *Dict) Update(o *Base) error {\n\tret := C.PyDict_Update(d.c(), o.c())\n\treturn int2Err(ret)\n}\n\n// MergeFromSeq2 merges key values pairs from the Object o (which must be an\n// iterable object, where each item is an iterable of length 2 - the key value\n// pairs).  If override is true then the last key value pair with the same key\n// wins, otherwise the first instance does (where an instance already in d\n// counts before any in o).\nfunc (d *Dict) MergeFromSeq2(o *Base, override bool) error {\n\tover := 0\n\tif override {\n\t\tover = 1\n\t}\n\tret := C.PyDict_MergeFromSeq2(d.c(), o.c(), C.int(over))\n\treturn int2Err(ret)\n}\n\n// Map returns a Go map that contains the values from the Python dictionary,\n// indexed by the keys.  The keys and values are the same as in the Python\n// dictionary, but changes to the Go map are not propogated back to the Python\n// dictionary.\n//\n// Note: the map holds borrowed references\nfunc (d *Dict) Map() map[*Base]*Base {\n\tm := make(map[*Base]*Base, d.Size())\n\tvar p C.Py_ssize_t\n\tvar k *C.PyObject\n\tvar v *C.PyObject\n\tfor int(C.PyDict_Next(d.c(), &p, &k, &v)) != 0 {\n\t\tkey := newObject(k)\n\t\tvalue := newObject(v)\n\t\tm[key] = value\n\t}\n\treturn m\n}\n\n// MapString is similar to Map, except that the keys are first converted to\n// strings.  If the keys are not all Python strings, then an error is returned.\n//\n// Note: the map holds borrowed references\nfunc (d *Dict) MapString() (map[string]*Base, error) {\n\tm := make(map[string]*Base, d.Size())\n\tvar p DictIter\n\tvar k, v *Base\n\tfor d.Next(&p, &k, &v) {\n\t\ts, ok := AsString(k)\n\t\tif !ok {\n\t\t\treturn nil, TypeError.Err(\"%v is not a string\", k)\n\t\t}\n\t\tm[s.String()] = v\n\t}\n\treturn m, nil\n}\n\ntype DictIter C.Py_ssize_t\n\n// Iterate over all key-value pairs in the dictionary d. \n// The Py_ssize_t referred to by ppos must be initialized to 0 prior to the first call to this function \n// to start the iteration; the function returns true for each pair in the dictionary, and false once all\n// pairs have been reported. The parameters pkey and pvalue should either point to PyObject* variables\n// that will be filled in with each key and value, respectively, or may be NULL. Any references returned\n// through them are borrowed. ppos should not be altered during iteration. Its value represents offsets\n// within the internal dictionary structure, and since the structure is sparse, the offsets are not consecutive.\nfunc (d *Dict) Next(pos *DictIter, k, v **Base) bool {\n\tk1 := (**C.PyObject)(unsafe.Pointer(k))\n\tv1 := (**C.PyObject)(unsafe.Pointer(v))\n\treturn C.PyDict_Next(d.c(), (*C.Py_ssize_t)(pos), k1, v1) != 0\n}\n\n"
  },
  {
    "path": "error.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline void incref(PyObject *obj) { Py_INCREF(obj); }\n// static inline void decref(PyObject *obj) { Py_DECREF(obj); }\n// static inline void xdecref(PyObject *obj) { Py_XDECREF(obj); }\nimport \"C\"\nimport \"fmt\"\nimport \"syscall\"\nimport \"strings\"\nimport \"runtime\"\nimport \"github.com/qiniu/errors\"\n\n// Error represents a Python exception as a Go struct that implements the\n// error interface.  It allows Go code to handle Python exceptions in an\n// idiomatic Go fashion.\ntype Error struct {\n\tKind  *Base\n\tValue *Base\n\ttb    *C.PyObject\n}\n\nfunc newError(kind, val *Base, tb *C.PyObject) *Error {\n\te := &Error{kind, val, tb}\n\truntime.SetFinalizer(e, (*Error).release)\n\treturn e\n}\n\nfunc (e *Error) release() error {\n\tif e.Kind != nil {\n\t\te.Kind.Decref()\n\t\te.Value.Decref()\n\t\te.Kind = nil\n\t\te.Value = nil\n\t\tif e.tb != nil {\n\t\t\tC.decref(e.tb)\n\t\t\te.tb = nil\n\t\t}\n\t}\n\treturn nil\n}\n\n// Error() returns a string representation of the Python exception represented\n// by the Error e.  This is the same as the final line of the Python output from\n// an uncaught exception.\nfunc (e *Error) Error() string {\n\tkind := e.Kind.String()\n\tif strings.HasPrefix(kind, \"<type 'exceptions.\") {\n\t\tkind = kind[18:len(kind)-2]\n\t}\n\treturn kind + \": \" + e.Value.String()\n}\n\n/*\n// Matches returns true if e.Kind matches the exception in exc.  If exc is a\n// Class, then true is returned if e.Kind is an instance.  If exc is a Tuple,\n// then all elements (and recursively for sub elements) are searched for a\n// match.\nfunc (e *Error) Matches(exc Object) bool {\n\treturn C.PyErr_GivenExceptionMatches(c(e.Kind), c(exc)) != 0\n}\n*/\n\n// Normalize adjusts e.Kind/e.Value in the case that the values aren't\n// normalized to start with.  It's possible that an Error returned from Python\n// might have e.Kind be a Class, with e.Value not being an instance of that\n// class, Normalize will fix this.  The separate normalization is implemented in\n// Python to improve performance.\nfunc (e *Error) Normalize() {\n\texc := e.Kind.c()\n\tval := e.Value.c()\n\ttb := e.tb\n\tC.PyErr_NormalizeException(&exc, &val, &tb)\n\te.Kind = newObject(exc)\n\te.Value = newObject(val)\n\te.tb = tb\n}\n\n// NewErrorV returns a new Error of the specified kind, and with the given\n// value.\nfunc NewErrorV(kind *Base, value *Base) *Error {\n\tkind.Incref()\n\tvalue.Incref()\n\treturn newError(kind, value, nil)\n}\n\n// NewError returns a new Error of the specified kind, and with the value\n// being a new String containing the string created the given format and args.\nfunc NewError(kind *Base, format string, args ...interface{}) *Error {\n\tmsg := fmt.Sprintf(format, args...)\n\tkind.Incref()\n\tval := NewString(msg)\n\treturn newError(kind, &val.Base, nil)\n}\n\nfunc Raise(err error) {\n\n\tvar val *C.PyObject\n\tvar exc = C.PyExc_Exception\n\n\te, ok := err.(*Error)\n\tif ok {\n\t\texc = e.Kind.c()\n\t\tval = e.Value.c()\n\t} else {\n\t\tv := NewString(errors.Detail(err))\n\t\tval = v.c()\n\t\tdefer C.decref(val)\n\t}\n\tC.PyErr_SetObject(exc, val)\n}\n\nfunc GetException() error {\n\treturn exception()\n}\n\nfunc exceptionRaised() bool {\n\treturn C.PyErr_Occurred() != nil\n}\n\nfunc exception() error {\n\tif C.PyErr_Occurred() == nil {\n\t\treturn syscall.EFAULT\n\t}\n\n\tvar t, v, tb *C.PyObject\n\tC.PyErr_Fetch(&t, &v, &tb)\n\n\treturn newError(newObject(t), newObject(v), tb)\n}\n\nfunc ssize_t2Int64Err(s C.Py_ssize_t) (int64, error) {\n\tif s < 0 {\n\t\treturn 0, exception()\n\t}\n\treturn int64(s), nil\n}\n\nfunc int2BoolErr(i C.int) (bool, error) {\n\tif i < 0 {\n\t\treturn false, exception()\n\t}\n\treturn i > 0, nil\n}\n\nfunc int2Err(i C.int) error {\n\tif i < 0 {\n\t\treturn exception()\n\t}\n\treturn nil\n}\n\nfunc obj2ObjErr(obj *C.PyObject) (*Base, error) {\n\tif obj == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newObject(obj), nil\n}\n\n"
  },
  {
    "path": "examples/gomodule/gomodule.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"github.com/qiniu/log\"\n\t\"github.com/qiniu/py\"\n)\n\n// -------------------------------------------------------------------\n\ntype FooModule struct {\n}\n\nfunc (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {\n\tvar i int\n\tvar s string\n\terr = py.Parse(args, &i, &s)\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(\"call foo.bar:\", i, s)\n\treturn py.IncNone(), nil\n}\n\nfunc (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {\n\tvar i int\n\tvar s []string\n\terr = py.ParseV(args, &i, &s)\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(\"call foo.bar2:\", i, s)\n\treturn py.IncNone(), nil\n}\n\n// -------------------------------------------------------------------\n\nconst pyCode = `\n\nimport foo\nfoo.bar(1, 'Hello')\nfoo.bar2(1, 'Hello', 'world!')\n`\n\nfunc main() {\n\n\tgomod, err := py.NewGoModule(\"foo\", \"\", new(FooModule))\n\tif err != nil {\n\t\tlog.Fatal(\"NewGoModule failed:\", err)\n\t}\n\tdefer gomod.Decref()\n\n\tcode, err := py.Compile(pyCode, \"\", py.FileInput)\n\tif err != nil {\n\t\tlog.Fatal(\"Compile failed:\", err)\n\t}\n\tdefer code.Decref()\n\n\tmod, err := py.ExecCodeModule(\"test\", code.Obj())\n\tif err != nil {\n\t\tlog.Fatal(\"ExecCodeModule failed:\", err)\n\t}\n\tdefer mod.Decref()\n}\n\n// -------------------------------------------------------------------\n\n"
  },
  {
    "path": "exc.go",
    "content": "package py\n\n// #include <Python.h>\nimport \"C\"\n\nvar (\n\tBaseException             = newException(C.PyExc_BaseException)\n\tException                 = newException(C.PyExc_Exception)\n\tStopIteration             = newException(C.PyExc_StopIteration)\n\tGeneratorExit             = newException(C.PyExc_GeneratorExit)\n\tStandardError             = newException(C.PyExc_StandardError)\n\tArithmeticError           = newException(C.PyExc_ArithmeticError)\n\tLookupError               = newException(C.PyExc_LookupError)\n\tAssertionError            = newException(C.PyExc_AssertionError)\n\tAttributeError            = newException(C.PyExc_AttributeError)\n\tEOFError                  = newException(C.PyExc_EOFError)\n\tFloatingPointError        = newException(C.PyExc_FloatingPointError)\n\tEnvironmentError          = newException(C.PyExc_EnvironmentError)\n\tIOError                   = newException(C.PyExc_IOError)\n\tOSError                   = newException(C.PyExc_OSError)\n\tImportError               = newException(C.PyExc_ImportError)\n\tIndexError                = newException(C.PyExc_IndexError)\n\tKeyError                  = newException(C.PyExc_KeyError)\n\tKeyboardInterrupt         = newException(C.PyExc_KeyboardInterrupt)\n\tMemoryError               = newException(C.PyExc_MemoryError)\n\tNameError                 = newException(C.PyExc_NameError)\n\tOverflowError             = newException(C.PyExc_OverflowError)\n\tRuntimeError              = newException(C.PyExc_RuntimeError)\n\tNotImplementedError       = newException(C.PyExc_NotImplementedError)\n\tSyntaxError               = newException(C.PyExc_SyntaxError)\n\tIndentationError          = newException(C.PyExc_IndentationError)\n\tTabError                  = newException(C.PyExc_TabError)\n\tReferenceError            = newException(C.PyExc_ReferenceError)\n\tSystemError               = newException(C.PyExc_SystemError)\n\tSystemExit                = newException(C.PyExc_SystemExit)\n\tTypeError                 = newException(C.PyExc_TypeError)\n\tUnboundLocalError         = newException(C.PyExc_UnboundLocalError)\n\tUnicodeError              = newException(C.PyExc_UnicodeError)\n\tUnicodeEncodeError        = newException(C.PyExc_UnicodeEncodeError)\n\tUnicodeDecodeError        = newException(C.PyExc_UnicodeDecodeError)\n\tUnicodeTranslateError     = newException(C.PyExc_UnicodeTranslateError)\n\tValueError                = newException(C.PyExc_ValueError)\n\tZeroDivisionError         = newException(C.PyExc_ZeroDivisionError)\n\tBufferError               = newException(C.PyExc_BufferError)\n\tMemoryErrorInst           = newException(C.PyExc_MemoryErrorInst)\n\tRecursionErrorInst        = newException(C.PyExc_RecursionErrorInst)\n\tWarning                   = newException(C.PyExc_Warning)\n\tUserWarning               = newException(C.PyExc_UserWarning)\n\tDeprecationWarning        = newException(C.PyExc_DeprecationWarning)\n\tPendingDeprecationWarning = newException(C.PyExc_PendingDeprecationWarning)\n\tSyntaxWarning             = newException(C.PyExc_SyntaxWarning)\n\tRuntimeWarning            = newException(C.PyExc_RuntimeWarning)\n\tFutureWarning             = newException(C.PyExc_FutureWarning)\n\tImportWarning             = newException(C.PyExc_ImportWarning)\n\tUnicodeWarning            = newException(C.PyExc_UnicodeWarning)\n\tBytesWarning              = newException(C.PyExc_BytesWarning)\n)\n"
  },
  {
    "path": "exception.go",
    "content": "package py\n\n// #include <Python.h>\nimport \"C\"\nimport \"unsafe\"\n\ntype ExceptionClass struct {\n\tBase\n\to C.PyBaseExceptionObject\n}\n\nfunc newException(obj *C.PyObject) *ExceptionClass {\n\treturn (*ExceptionClass)(unsafe.Pointer(obj))\n}\n\n// ErrV returns a new Error of the specified kind, and with the given value.\nfunc (kind *ExceptionClass) ErrV(obj *Base) *Error {\n\treturn NewErrorV(&kind.Base, obj)\n}\n\n// Err returns a new Error of the specified kind, and with the value being a\n// new String containing the string created the given format and args.\nfunc (kind *ExceptionClass) Err(format string, args ...interface{}) *Error {\n\treturn NewError(&kind.Base, format, args...)\n}\n"
  },
  {
    "path": "float.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline double floatCheck(PyObject *o) { return PyFloat_Check(o); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Float struct {\n\tBase\n\tNumberProtocol\n\to C.PyFloatObject\n}\n\n// FloatType is the Type object that represents the Float type.\nvar FloatType = (*Type)(unsafe.Pointer(&C.PyFloat_Type))\n\nfunc newFloat(obj *C.PyObject) *Float {\n\treturn (*Float)(unsafe.Pointer(obj))\n}\n\nfunc NewFloat(i float64) *Float {\n\treturn newFloat(C.PyFloat_FromDouble(C.double(i)))\n}\n\nfunc AsFloat(o *Base) (v *Float, ok bool) {\n\tif ok = C.floatCheck(o.c()) != 0; ok {\n\t\tv = newFloat(o.c())\n\t}\n\treturn\n}\n\nfunc NewFloatFromString(s string) *Float {\n\tcs := NewString(s)\n\treturn newFloat(C.PyFloat_FromString((*C.PyObject)(unsafe.Pointer(cs.Obj())), nil))\n}\n\nfunc (f *Float) Float() float64 {\n\treturn float64(C.PyFloat_AsDouble(f.c()))\n}\n"
  },
  {
    "path": "goargs.go",
    "content": "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// ------------------------------------------------------------------------------------------\n\nfunc ToInt(in *Base) (int, bool) {\n\n\tl, ok := ToLong(in)\n\treturn int(l), ok\n}\n\nfunc ToLong(in *Base) (int64, bool) {\n\n\tif v, ok := AsInt(in); ok {\n\t\treturn int64(v.Int()), true\n\t}\n\tif v, ok := AsLong(in); ok {\n\t\treturn int64(v.Long()), true\n\t}\n\treturn 0, false\n}\n\nfunc ToString(in *Base) (string, bool) {\n\n\tif v, ok := AsString(in); ok {\n\t\treturn v.String(), true\n\t}\n\treturn \"\", false\n}\n\nfunc ToInterface(in *Base) (v interface{}, ok bool) {\n\n\tif v, ok = ToLong(in); ok {\n\t\treturn\n\t} else if v, ok = ToString(in); ok {\n\t\treturn\n\t}\n\treturn\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc assignToMap(in *Base, out reflect.Value) (err error) {\n\n\tdict, ok := AsDict(in)\n\tif !ok {\n\t\terr = errors.Info(syscall.EINVAL, \"py.AssignTo\", \"uncompatible type\")\n\t\treturn\n\t}\n\n\tmapTy := out.Type()\n\tm := reflect.MakeMap(mapTy)\n\n\tkeyTy := mapTy.Key()\n\tvalTy := mapTy.Elem()\n\n\tlog.Debug(\"assignToMap:\", mapTy, keyTy, valTy)\n\n\tvar iter DictIter\n\tvar k, v *Base\n\tfor dict.Next(&iter, &k, &v) {\n\t\tkout := reflect.New(keyTy)\n\t\terr = AssignTo(k, kout.Interface())\n\t\tif err != nil {\n\t\t\terr = errors.Info(err, \"py.AssignTo\", \"assign map key\").Detail(err)\n\t\t\treturn\n\t\t}\n\t\tvout := reflect.New(valTy)\n\t\terr = AssignTo(v, vout.Interface())\n\t\tif err != nil {\n\t\t\terr = errors.Info(err, \"py.AssignTo\", \"assign map val\").Detail(err)\n\t\t\treturn\n\t\t}\n\t\tm.SetMapIndex(kout.Elem(), vout.Elem())\n\t}\n\n\tout.Set(m)\n\treturn nil\n}\n\nfunc assignToComplex(in *Base, out1 reflect.Value) (err error) {\n\n\tif out1.Kind() != reflect.Ptr {\n\t\terr = errors.Info(syscall.EINVAL, \"py.AssignTo\", \"not assignable\")\n\t\treturn\n\t}\n\n\tout := out1.Elem()\n\tswitch out.Kind() {\n\tcase reflect.Map:\n\t\treturn assignToMap(in, out)\n\tdefault:\n\t\terr = errors.Info(syscall.EINVAL, \"py.AssignTo\", \"unsupported input type\", reflect.TypeOf(out))\n\t\treturn\n\t}\n\treturn\n}\n\nfunc AssignTo(in *Base, out interface{}) (err error) {\n\n\tvar ok bool\n\tswitch v := out.(type) {\n\tcase *string:\n\t\t*v, ok = ToString(in)\n\tcase *int64:\n\t\t*v, ok = ToLong(in)\n\tcase *int:\n\t\t*v, ok = ToInt(in)\n\tcase *interface{}:\n\t\t*v, ok = ToInterface(in)\n\t\treturn\n\tdefault:\n\t\treturn assignToComplex(in, reflect.ValueOf(out))\n\t}\n\tif !ok {\n\t\terr = errors.Info(syscall.EINVAL, \"py.AssignTo\", \"can not convert type\", reflect.TypeOf(out))\n\t}\n\treturn\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc Parse(in *Tuple, out ...interface{}) (err error) {\n\n\tn := in.Size()\n\tif n != len(out) {\n\t\terr = errors.Info(syscall.EINVAL, \"py.Parse\", \"invalid argument count\")\n\t\treturn\n\t}\n\n\tfor i := 0; i < n; i++ {\n\t\tv2, err2 := in.GetItem(i)\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.Parse\", \"invalid argument\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t\terr2 = AssignTo(v2, out[i])\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.Parse\", \"assign argument failed\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t}\n\treturn\n}\n\nfunc ParseV(in *Tuple, out ...interface{}) (err error) {\n\n\tn1 := in.Size()\n\tn := len(out) - 1\n\tif n1 < n || n < 0 {\n\t\terr = errors.Info(syscall.EINVAL, \"py.ParseV\", \"argument count is not enough\")\n\t\treturn\n\t}\n\n\tslicePtr := reflect.TypeOf(out[n])\n\tif slicePtr.Kind() != reflect.Ptr {\n\t\terr = errors.Info(syscall.EINVAL, \"py.ParseV\", \"last argument is not a slice pointer\")\n\t\treturn\n\t}\n\n\tsliceTy := slicePtr.Elem()\n\tif sliceTy.Kind() != reflect.Slice {\n\t\terr = errors.Info(syscall.EINVAL, \"py.ParseV\", \"last argument is not a slice pointer\")\n\t\treturn\n\t}\n\n\tfor i := 0; i < n; i++ {\n\t\tv2, err2 := in.GetItem(i)\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.ParseV\", \"invalid argument\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t\terr2 = AssignTo(v2, out[i])\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.ParseV\", \"assign argument failed\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t}\n\n\tslice := reflect.MakeSlice(sliceTy, n1-n, n1-n)\n\tfor i := n; i < n1; i++ {\n\t\tv2, err2 := in.GetItem(i)\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.ParseV\", \"invalid argument\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t\terr2 = AssignTo(v2, slice.Index(i-n).Addr().Interface())\n\t\tif err2 != nil {\n\t\t\terr = errors.Info(err2, \"py.ParseV\", \"assign argument failed\", i+1).Detail(err2)\n\t\t\treturn\n\t\t}\n\t}\n\treflect.ValueOf(out[n]).Elem().Set(slice)\n\treturn\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "gofunction.c",
    "content": "#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_meth = (PyCFunction)goClassCallMethodKwds;\n\t\td->ml_flags = METH_VARARGS | METH_KEYWORDS;\n\t\tbreak;\n\tcase 2:\n\t\td->ml_meth = (PyCFunction)goClassCallMethodArgs;\n\t\td->ml_flags = METH_VARARGS;\n\t\tbreak;\n\tdefault:\n\t\treturn -1;\n\t}\n\treturn 0;\n}\n\n"
  },
  {
    "path": "gofunction.go",
    "content": "package py\n\n/*\n#include <Python.h>\n#include \"gofunction.h\"\n\nstatic inline void decref(PyObject *obj) { Py_DECREF(obj); }\n*/\nimport \"C\"\nimport \"unsafe\"\nimport \"reflect\"\n\ntype Closure struct { // closure = self.method\n\tSelf reflect.Value\n\tMethod reflect.Value\n\tmethodDef C.PyMethodDef\n}\n\nfunc (closure *Closure) NewFunction(name string, nin int, doc string) *Base {\n\n\td := &closure.methodDef\n\td.ml_name = C.CString(name)\n\tdefer C.free(unsafe.Pointer(d.ml_name))\n\n\tif C.setMethod(d, C.int(nin)) != 0 {\n\t\tpanic(\"Invalid arguments: nin\")\n\t}\n\tif doc != \"\" {\n\t\td.ml_doc = C.CString(doc)\n\t\tdefer C.free(unsafe.Pointer(d.ml_doc))\n\t}\n\n\tctx := uintptr(unsafe.Pointer(closure))\n\tself := C.PyLong_FromLongLong(C.longlong(ctx))\n\tdefer C.decref(self)\n\n\tf := C.PyCFunction_NewEx(d, self, nil)\n\treturn (*Base)(unsafe.Pointer(f))\n}\n\n//export goClassCallMethodArgs\nfunc goClassCallMethodArgs(obj, args unsafe.Pointer) unsafe.Pointer {\n\n\t// Unpack context and self pointer from obj\n\tt := (*C.PyObject)(obj)\n\tclosure := (*Closure)(unsafe.Pointer(uintptr(C.PyLong_AsLongLong(t))))\n\n\t// Get args ready to use, by turning it into a pointer of the appropriate\n\t// type\n\ta := (*Tuple)(args)\n\n\tin := []reflect.Value{closure.Self, reflect.ValueOf(a)}\n\tout := closure.Method.Call(in)\n\n\terr := out[1].Interface()\n\tif err != nil {\n\t\tRaise(err.(error))\n\t\treturn nil\n\t}\n\n\tret := out[0].Interface().(*Base)\n\treturn unsafe.Pointer(ret)\n}\n\n//export goClassCallMethodKwds\nfunc goClassCallMethodKwds(obj, args, kwds unsafe.Pointer) unsafe.Pointer {\n\n\t// Unpack context and self pointer from obj\n\tt := (*C.PyObject)(obj)\n\tclosure := (*Closure)(unsafe.Pointer(uintptr(C.PyLong_AsLongLong(t))))\n\n\t// Get args and kwds ready to use, by turning them into pointers of the\n\t// appropriate type\n\ta := (*Tuple)(args)\n\tk := (*Dict)(kwds)\n\n\tin := []reflect.Value{closure.Self, reflect.ValueOf(a), reflect.ValueOf(k)}\n\tout := closure.Method.Call(in)\n\n\terr := out[1].Interface()\n\tif err != nil {\n\t\tRaise(err.(error))\n\t\treturn nil\n\t}\n\n\tret := out[0].Interface().(*Base)\n\treturn unsafe.Pointer(ret)\n}\n\n"
  },
  {
    "path": "gofunction.h",
    "content": "#ifndef QBOX_GOPY_GOFUNCTION_H\n#define QBOX_GOPY_GOFUNCTION_H\n\nint setMethod(PyMethodDef* d, int nin);\n\n#endif /* _GO_PYTHON_UTILS_H */\n\n"
  },
  {
    "path": "gomodule.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline void decref(PyObject *obj) { Py_DECREF(obj); }\nimport \"C\"\nimport \"unsafe\"\n\n// ------------------------------------------------------------------------------------------\n\ntype GoModule struct {\n\t*Module\n\tCtx RegisterCtx\n}\n\nfunc NewGoModule(name string, doc string, self interface{}) (mod GoModule, err error) {\n\n\tcName := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cName))\n\n\tvar mdoc *C.char\n\tif doc != \"\" {\n\t\tmdoc = C.CString(doc)\n\t\tdefer C.free(unsafe.Pointer(mdoc))\n\t}\n\n\tm := C.Py_InitModule4(cName, nil, mdoc, nil, C.PYTHON_API_VERSION)\n\tif m == nil {\n\t\terr = exception()\n\t\treturn\n\t}\n\n\tmod.Module = (*Module)(unsafe.Pointer(m))\n\tmod.Ctx = Register(mod.Module.Dict(), name + \".\", self)\n\treturn\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "gomodule_test.go",
    "content": "package py\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\n// ------------------------------------------------------------------------------------------\n\ntype FooModule struct {\n}\n\nfunc (r *FooModule) Py_bar(args *Tuple) (ret *Base, err error) {\n\tvar i int\n\tvar s []string\n\terr = ParseV(args, &i, &s)\n\tif err != nil {\n\t\treturn\n\t}\n\tfmt.Println(\"call foo.bar:\", i, s)\n\treturn IncNone(), nil\n}\n\n// ------------------------------------------------------------------------------------------\n\ntype gomoduleCase struct {\n\texp string\n\tname string\n}\n\nvar g_gomoduleCases = []gomoduleCase{\n\t{\n`import foo\nfoo.bar(1, 'Hello')\n`, \"test\"},\n}\n\nfunc TestGoModule(t *testing.T) {\n\n\tgomod, err := NewGoModule(\"foo\", \"\", new(FooModule))\n\tif err != nil {\n\t\tt.Fatal(\"NewGoModule failed:\", err)\n\t}\n\tdefer gomod.Decref()\n\n\tfor _, c := range g_gomoduleCases {\n\n\t\tcode, err := Compile(c.exp, \"\", FileInput)\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Compile failed:\", err)\n\t\t}\n\t\tdefer code.Decref()\n\n\t\tmod, err := ExecCodeModule(c.name, code.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"ExecCodeModule failed:\", err)\n\t\t}\n\t\tdefer mod.Decref()\n\t}\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "goregister.go",
    "content": "package py\n\nimport \"reflect\"\nimport \"strings\"\nimport \"github.com/qiniu/log\"\n\n// ------------------------------------------------------------------------------------------\n\n// Note: Methods take the receiver as the first argument, which the want\n// signature doesn't include.\nfunc sigMatches(got, want reflect.Type) bool {\n\n\tnin := want.NumIn()\n\tif got.NumIn()-1 != nin {\n\t\treturn false\n\t}\n\n\tnout := want.NumOut()\n\tif got.NumOut() != nout {\n\t\treturn false\n\t}\n\n\tfor i := 0; i < nin; i++ {\n\t\tif got.In(i+1) != want.In(i) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tfor i := 0; i < nout; i++ {\n\t\tif got.Out(i) != want.Out(i) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// ------------------------------------------------------------------------------------------\n\nvar typUnaryFunc = reflect.TypeOf(func() (*Base, error)(nil))\nvar typBinaryCallFunc = reflect.TypeOf(func(*Tuple) (*Base, error)(nil))\nvar typTernaryCallFunc = reflect.TypeOf(func(*Tuple, *Dict) (*Base, error)(nil))\n\ntype RegisterCtx []*Closure // 只是让对象不被gc\n\nfunc Register(dict *Dict, nsprefix string, self interface{}) (ctx RegisterCtx) {\n\n\ttyp := reflect.TypeOf(self)\n\tselfv := reflect.ValueOf(self)\n\n\tnmethod := typ.NumMethod()\n\n\tfor i := 0; i < nmethod; i++ {\n\t\tmethod := typ.Method(i)\n\t\tmtype := method.Type\n\t\tmname := method.Name\n\t\tif mtype.PkgPath() != \"\" || !strings.HasPrefix(mname, \"Py_\") {\n\t\t\tcontinue\n\t\t}\n\t\tnin := mtype.NumIn()\n\t\tname := mname[3:]\n\t\tfullname := nsprefix + name\n\t\tif nin == 3 && sigMatches(mtype, typTernaryCallFunc) || nin == 2 && sigMatches(mtype, typBinaryCallFunc) {\n\t\t\tclosure := &Closure{Self: selfv, Method: method.Func}\n\t\t\tf := closure.NewFunction(fullname, nin, \"\")\n\t\t\tdict.SetItemString(name, f)\n\t\t\tf.Decref()\n\t\t\tctx = append(ctx, closure)\n\t\t\tlog.Debug(\"Register\", fullname)\n\t\t} else {\n\t\t\tlog.Warnf(\"Invalid signature of method %s, register failed\", fullname)\n\t\t\tcontinue\n\t\t}\n\t}\n\treturn\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "goregister_test.go",
    "content": "package py\n\nimport (\n\t\"testing\"\n\t\"github.com/qiniu/log\"\n)\n\nfunc init() {\n\tlog.SetOutputLevel(0)\n}\n\n// ------------------------------------------------------------------------------------------\n\ntype Foo struct {\n}\n\nfunc (r *Foo) Py_foo(args *Tuple) (*Base, error) {\n\treturn IncNone(), nil\n}\n\nfunc (r *Foo) Py_bar(args *Tuple) (*Base) {\n\treturn IncNone()\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc _TestRegister(t *testing.T) {\n\n\tdict := NewDict()\n\tdefer dict.Decref()\n\n\tRegister(dict, \"\", new(Foo))\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "int.go",
    "content": "// Copyright 2011 Julian Phillips.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage py\n\n// #include <Python.h>\n// static inline int intCheck(PyObject *o) { return PyInt_Check(o); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Int struct {\n\tBase\n\tNumberProtocol\n\to C.PyIntObject\n}\n\n// IntType is the Type object that represents the Int type.\nvar IntType = (*Type)(unsafe.Pointer(&C.PyInt_Type))\n\nfunc newInt(obj *C.PyObject) *Int {\n\treturn (*Int)(unsafe.Pointer(obj))\n}\n\nfunc NewInt(i int) *Int {\n\treturn newInt(C.PyInt_FromLong(C.long(i)))\n}\n\nfunc NewInt64(i int64) *Int {\n\treturn newInt(C.PyInt_FromSsize_t(C.Py_ssize_t(i)))\n}\n\nfunc AsInt(o *Base) (v *Int, ok bool) {\n\tif ok = C.intCheck(o.c()) != 0; ok {\n\t\tv = newInt(o.c())\n\t}\n\treturn\n}\n\nfunc (i *Int) Int() int {\n\treturn int(C.PyInt_AsLong(i.c()))\n}\n\n"
  },
  {
    "path": "long.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline long longCheck(PyObject *o) { return PyLong_Check(o); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Long struct {\n\tBase\n\tNumberProtocol\n\to C.PyLongObject\n}\n\n// LongType is the Type object that represents the Long type.\nvar LongType = (*Type)(unsafe.Pointer(&C.PyLong_Type))\n\nfunc newLong(obj *C.PyObject) *Long {\n\treturn (*Long)(unsafe.Pointer(obj))\n}\n\nfunc NewLong(i int64) *Long {\n\treturn newLong(C.PyLong_FromLongLong(C.longlong(i)))\n}\n\nfunc AsLong(o *Base) (v *Long, ok bool) {\n\tif ok = C.longCheck(o.c()) != 0; ok {\n\t\tv = newLong(o.c())\n\t}\n\treturn\n}\n\nfunc (l *Long) Long() int64 {\n\treturn int64(C.PyLong_AsLongLong(l.c()))\n}\n\n"
  },
  {
    "path": "module.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int moduleCheck(PyObject *o) { return PyModule_Check(o); }\n// static inline int moduleCheckE(PyObject *o) { return PyModule_CheckExact(o); }\n// static inline void decref(PyObject *obj) { Py_DECREF(obj); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Module struct {\n\tBase\n\to C.PyObject\n}\n\n// ModuleType is the Type object that represents the Module type.\nvar ModuleType = (*Type)(unsafe.Pointer(&C.PyModule_Type))\n\nfunc newModule(obj *C.PyObject) *Module {\n\treturn (*Module)(unsafe.Pointer(obj))\n}\n\nfunc Import(name string) (*Module, error) {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\n\tpyName := C.PyString_FromString(s)\n\tdefer C.decref(pyName)\n\n\tobj := C.PyImport_Import(pyName)\n\tif obj == nil {\n\t\treturn nil, exception()\n\t}\n\n\treturn newModule(obj), nil\n}\n\nfunc ExecCodeModule(name string, code *Base) (*Module, error) {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyImport_ExecCodeModule(s, code.c())\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newModule(ret), nil\n}\n\nfunc NewModule(name string) (*Module, error) {\n\tcname := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cname))\n\n\tret := C.PyModule_New(cname)\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\n\treturn newModule(ret), nil\n}\n\nfunc AsModule(o *Base) (v *Module, ok bool) {\n\tif ok = C.moduleCheck(o.c()) != 0; ok {\n\t\tv = newModule(o.c())\n\t}\n\treturn\n}\n\nfunc (mod *Module) CheckExact() bool {\n\treturn C.moduleCheckE(mod.c()) != 0\n}\n\n// Return value: Borrowed reference.\nfunc (mod *Module) Dict() *Dict {\n\tret := C.PyModule_GetDict(mod.c())\n\treturn newDict(ret)\n}\n\n// Return module‘s __name__ value. If the module does not provide one, or if it is not a string, \n// SystemError is raised and NULL is returned.\nfunc (mod *Module) Name() (string, error) {\n\tret := C.PyModule_GetName(mod.c())\n\tif ret == nil {\n\t\treturn \"\", exception()\n\t}\n\treturn C.GoString(ret), nil\n}\n\nfunc (mod *Module) Filename() (string, error) {\n\tret := C.PyModule_GetFilename(mod.c())\n\tif ret == nil {\n\t\treturn \"\", exception()\n\t}\n\treturn C.GoString(ret), nil\n}\n\nfunc (mod *Module) AddObject(name string, obj *Base) error {\n\tif obj == nil {\n\t\treturn AssertionError.Err(\"ValueError: obj == nil!\")\n\t}\n\n\tcname := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cname))\n\n\tret := C.PyModule_AddObject(mod.c(), cname, obj.c())\n\tif ret < 0 {\n\t\treturn exception()\n\t}\n\n\treturn nil\n}\n\nfunc (mod *Module) AddIntConstant(name string, value int) error {\n\tcname := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cname))\n\n\tret := C.PyModule_AddIntConstant(mod.c(), cname, C.long(value))\n\tif ret < 0 {\n\t\treturn exception()\n\t}\n\n\treturn nil\n}\n\nfunc (mod *Module) AddStringConstant(name, value string) error {\n\tcname := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cname))\n\n\tcvalue := C.CString(value)\n\tdefer C.free(unsafe.Pointer(cvalue))\n\n\tret := C.PyModule_AddStringConstant(mod.c(), cname, cvalue)\n\tif ret < 0 {\n\t\treturn exception()\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "module_test.go",
    "content": "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 = []moduleCase{\n\t{`\ntbl = 'dn_5m'\ndef init(cat):\n\tglobal tbl\n\ttbl = tbl + cat\n\treturn True\n\t`, \"foo\", \"True\", \"dn_5m_stage\"},\n}\n\nfunc TestModule(t *testing.T) {\n\n\tfor _, c := range g_moduleCases {\n\t\tcode, err := Compile(c.exp, \"\", FileInput)\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Compile failed:\", err)\n\t\t}\n\t\tdefer code.Decref()\n\n\t\tmod, err := ExecCodeModule(c.name, code.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"ExecCodeModule failed:\", err)\n\t\t}\n\t\tdefer mod.Decref()\n\n\t\targ1 := NewString(\"_stage\")\n\t\tdefer arg1.Decref()\n\n\t\tret, err := mod.CallMethodObjArgs(\"init\", arg1.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"CallMethodObjArgs failed:\", err)\n\t\t}\n\t\tdefer ret.Decref()\n\n\t\tif ret.String() != c.ret {\n\t\t\tt.Fatal(\"CallMethodObjArgs ret:\", ret.String(), c.ret)\n\t\t}\n\n\t\tglobals, _ := mod.GetAttrString(\"tbl\")\n\t\tdefer globals.Decref()\n\n\t\tif globals.String() != c.globals {\n\t\t\tt.Fatal(\"mod.GetAttrString('tbl') ret:\", globals.String(), c.globals)\n\t\t}\n\n\t\tdict := mod.Dict() // don't need Decref\n\t\ttbl2 := dict.GetItemString(\"tbl\") // don't need Decref\n\t\tif tbl2.String() != c.globals {\n\t\t\tt.Fatal(\"mod.Dict.GetItemString('tbl') ret:\", tbl2.String(), c.globals)\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "none.go",
    "content": "package py\n\n/*\n#include <Python.h>\n\nstatic inline PyObject* incNone() { Py_RETURN_NONE; }\n*/\nimport \"C\"\n\n// ------------------------------------------------------------------------------------------\n\nfunc IncNone() *Base {\n\treturn newObject(C.incNone())\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "number.go",
    "content": "// Copyright 2011 Julian Phillips.  All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\npackage py\n\n// #include <Python.h>\nimport \"C\"\nimport \"unsafe\"\n\n// NumberProtocol is a 0-sized type that can be embedded in concrete types after\n// the AbstractObject to provide access to the suite of methods that Python\n// calls the \"Number Protocol\".\ntype NumberProtocol struct{}\n\nfunc cnp(n *NumberProtocol) *C.PyObject {\n\treturn (*C.PyObject)(unsafe.Pointer(n))\n}\n\n// Add returns the result of adding n and obj.  The equivalent Python is \"n +\n// obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Add(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Add(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Subtract returns the result of subtracting obj from n.  The equivalent Python\n// is \"n - obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Subtract(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Subtract(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Multiply returns the result of multiplying n by obj.  The equivalent Python\n// is \"n * obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Multiply(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Multiply(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Divide returns the result of dividing n by obj.  The equivalent Python is \"n\n// / obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Divide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Divide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// FloorDivide returns the floor of dividing n obj obj.\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) FloorDivide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_FloorDivide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// TrueDivide returns the ... TODO\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) TrueDivide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_TrueDivide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Remainder returns the remainder of dividing n by obj.  The equivalent Python\n// is \"n % obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Remainder(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Remainder(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Divmod returns the result of the Python \"divmod(n, obj)\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Divmod(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Divmod(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Power returns the result of the Python \"pow(n, obj1, obj2)\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Power(obj1, obj2 *Base) (*Base, error) {\n\tret := C.PyNumber_Power(cnp(n), obj1.c(), obj2.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Negative returns the negation of n.  The equivalent Python is \"-n\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Negative() (*Base, error) {\n\tret := C.PyNumber_Negative(cnp(n))\n\treturn obj2ObjErr(ret)\n}\n\n// Positive returns the positive of n.  The equivalent Python is \"+n\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Positive() (*Base, error) {\n\tret := C.PyNumber_Positive(cnp(n))\n\treturn obj2ObjErr(ret)\n}\n\n// Absolute returns the absolute value of n.  The equivalent Python is \"abs(n)\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Absolute() (*Base, error) {\n\tret := C.PyNumber_Absolute(cnp(n))\n\treturn obj2ObjErr(ret)\n}\n\n// Invert returns the bitwise negation of n.  The equivalent Python is \"-n\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Invert() (*Base, error) {\n\tret := C.PyNumber_Invert(cnp(n))\n\treturn obj2ObjErr(ret)\n}\n\n// Lshift returns the result of left shifting n by obj.  The equivalent Python\n// is \"n << obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Lshift(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Lshift(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Rshift returns the result of right shifting n by obj.  The equivalent Python\n// is \"n << obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Rshift(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Rshift(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// And returns the bitwise and of n and obj.  The equivalent Python is \"n &\n// obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) And(obj *Base) (*Base, error) {\n\tret := C.PyNumber_And(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Xor returns the bitwise xor of n and obj.  The equivalent Python is \"n ^\n// obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Xor(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Xor(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Or returns the bitwise or of n and obj.  The equivalent Python is \"n | obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) Or(obj *Base) (*Base, error) {\n\tret := C.PyNumber_Or(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceAdd returns the result of adding n and obj.  This is done in place if\n// supported by n.  The equivalent Python is \"n += obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceAdd(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceAdd(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceSubtract returns the result of subtracting obj from n.  This is done\n// in place if supported by n.  The equivalent Python is \"n -= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceSubtract(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceSubtract(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceMultiply returns the result of multiplying n by obj.  This is done in\n// place if supported by n.  The equivalent Python is \"n *= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceMultiply(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceMultiply(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceDivide returns the result of dividing n by obj.  This is done in place\n// if supported by n.  The equivalent Python is \"n /= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceDivide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceDivide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// TODO returns the ...\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceFloorDivide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceFloorDivide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// TODO returns the ...\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceTrueDivide(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceTrueDivide(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceRemainder returns the remainder of n divided by obj.  This is done in\n// place if supported by n.  The equivalent Python is \"n %= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceRemainder(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceRemainder(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlacePower returns the result of the Python \"pow(n, obj1, obj2)\".  This is\n// done in place if supported by n.  If obj2 is None, then the Python \"n **=\n// obj\" is also equivalent, if obj2 is not None, there is no equivalent in\n// Python.\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlacePower(obj1, obj2 *Base) (*Base, error) {\n\tret := C.PyNumber_InPlacePower(cnp(n), obj1.c(), obj2.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceLshift returns the result of left shifting n by obj.  This is done in\n// place if supported by n.  The equivalent Python is \"n <<= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceLshift(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceLshift(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceRshift returns the result of right shifting n by obj.  This is done in\n// place if supported by n.  The equivalent Python is \"n >>= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceRshift(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceRshift(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceAnd returns the bitwise and of n and obj.  This is done in place if\n// supported by n.  The equivalent Python is \"n &= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceAnd(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceAnd(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceXor returns the bitwise xor of n and obj.  This is done in place if\n// supported by n.  The equivalent Python is \"n ^= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceXor(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceXor(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// InPlaceOr returns the bitwise or of n and obj.  This is done in place if\n// supported by n.  The equivalent Python is \"n |= obj\".\n//\n// Return value: New Reference.\nfunc (n *NumberProtocol) InPlaceOr(obj *Base) (*Base, error) {\n\tret := C.PyNumber_InPlaceOr(cnp(n), obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// PyNumber_Coerce: TODO\n\n// PyNumber_CoerceEx: TODO\n\n// PyNumber_Int: TODO\n\n// PyNumber_Long: TODO\n\n// PyNumber_Float: TODO\n\n// PyNumber_Index: TODO\n\n// PyNumber_ToBase: TODO\n\n// PyNumber_AsSsize_t: TODO\n"
  },
  {
    "path": "object.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline void incref(PyObject *obj) { Py_INCREF(obj); }\n// static inline void decref(PyObject *obj) { Py_DECREF(obj); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Op int\n\nconst (\n\tLT = Op(C.Py_LT)\n\tLE = Op(C.Py_LE)\n\tEQ = Op(C.Py_EQ)\n\tNE = Op(C.Py_NE)\n\tGT = Op(C.Py_GT)\n\tGE = Op(C.Py_GE)\n)\n\n// Base is an 0-sized type that can be embedded as the first item in\n// concrete types to provide the Object interface functions.\ntype Base struct {}\n\nfunc newObject(obj *C.PyObject) *Base {\n\treturn (*Base)(unsafe.Pointer(obj))\n}\n\nfunc (obj *Base) c() *C.PyObject {\n\treturn (*C.PyObject)(unsafe.Pointer(obj))\n}\n\nfunc (obj *Base) Obj() *Base {\n\treturn obj\n}\n\n// Init initialises obj.  It is equivalent to \"obj.__init__(*args, **kw)\" in\n// Python.\nfunc (obj *Base) Init(args *Tuple, kw *Dict) error {\n\treturn obj.Type().Init(obj, args, kw)\n}\n\n// Type returns a pointer to the Type that represents the type of this object in\n// Python.\nfunc (obj *Base) Type() *Type {\n\to := obj.c().ob_type\n\treturn newType((*C.PyObject)(unsafe.Pointer(o)))\n}\n\n// Decref decrements obj's reference count, obj may not be nil.\nfunc (obj *Base) Decref() {\n\tC.decref(obj.c())\n}\n\n// Incref increments obj's reference count, obj may not be nil.\nfunc (obj *Base) Incref() {\n\tC.incref(obj.c())\n}\n\n// IsTrue returns true if the value of obj is considered to be True.  This is\n// equivalent to \"if obj:\" in Python.\nfunc (obj *Base) IsTrue() bool {\n\tret := C.PyObject_IsTrue(obj.c())\n\tif ret < 0 {\n\t\tpanic(exception())\n\t}\n\treturn ret != 0\n}\n\n// Not returns true if the value of obj is considered to be False.  This is\n// equivalent to \"if not obj:\" in Python.\nfunc (obj *Base) Not() bool {\n\tret := C.PyObject_Not(obj.c())\n\tif ret < 0 {\n\t\tpanic(exception())\n\t}\n\treturn ret != 0\n}\n\n// HasAttr returns true if \"obj\" has the attribute \"name\".  This is equivalent\n// to the Python \"hasattr(obj, name)\".\nfunc (obj *Base) HasAttr(name *Base) bool {\n\tret := C.PyObject_HasAttr(obj.c(), name.c())\n\tif ret == 1 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// HasAttrString returns true if \"obj\" has the attribute \"name\".  This is\n// equivalent to the Python \"hasattr(obj, name)\".\nfunc (obj *Base) HasAttrString(name string) bool {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyObject_HasAttrString(obj.c(), s)\n\tif ret == 1 {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// GetAttr returns the attribute of \"obj\" with the name \"name\".  This is\n// equivalent to the Python \"obj.name\".\n//\n// Return value: New Reference.\nfunc (obj *Base) GetAttr(name *Base) (*Base, error) {\n\tret := C.PyObject_GetAttr(obj.c(), name.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Retrieve an attribute named attr_name from object o. Returns the attribute value\n// on success, or NULL on failure. This is the equivalent to the Python \"obj.name\".\n//\n// Return value: New reference.\nfunc (obj *Base) GetAttrString(name string) (*Base, error) {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyObject_GetAttrString(obj.c(), s)\n\treturn obj2ObjErr(ret)\n}\n\n// PyObject_GenericGetAttr : This is an internal helper function - we shouldn't\n// need to expose it ...\n\n// SetAttr sets the attribute of \"obj\" with the name \"name\" to \"value\".  This is\n// equivalent to the Python \"obj.name = value\".\nfunc (obj *Base) SetAttr(name, value *Base) error {\n\tret := C.PyObject_SetAttr(obj.c(), name.c(), value.c())\n\treturn int2Err(ret)\n}\n\n// SetAttrString sets the attribute of \"obj\" with the name \"name\" to \"value\".\n// This is equivalent to the Python \"obj.name = value\".\nfunc (obj *Base) SetAttrString(name string, value *Base) error {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyObject_SetAttrString(obj.c(), s, value.c())\n\treturn int2Err(ret)\n}\n\n// PyObject_GenericSetAttr : This is an internal helper function - we shouldn't\n// need to expose it ...\n\n// DelAttr deletes the attribute with the name \"name\" from \"obj\".  This is\n// equivalent to the Python \"del obj.name\".\nfunc (obj *Base) DelAttr(name *Base) error {\n\tret := C.PyObject_SetAttr(obj.c(), name.c(), nil)\n\treturn int2Err(ret)\n}\n\n// DelAttrString deletes the attribute with the name \"name\" from \"obj\".  This is\n// equivalent to the Python \"del obj.name\".\nfunc (obj *Base) DelAttrString(name string) error {\n\ts := C.CString(name)\n\tdefer C.free(unsafe.Pointer(s))\n\tret := C.PyObject_SetAttrString(obj.c(), s, nil)\n\treturn int2Err(ret)\n}\n\n// RichCompare compares \"obj\" with \"obj2\" using the specified operation (LE, GE\n// etc.), and returns the result.  The equivalent Python is \"obj op obj2\", where\n// op is the corresponding Python operator for op.\n//\n// Return value: New Reference.\nfunc (obj *Base) RichCompare(obj2 *Base, op Op) (*Base, error) {\n\tret := C.PyObject_RichCompare(obj.c(), obj2.c(), C.int(op))\n\treturn obj2ObjErr(ret)\n}\n\n// RichCompare compares \"obj\" with \"obj2\" using the specified operation (LE, GE\n// etc.), and returns true or false.  The equivalent Python is \"obj op obj2\",\n// where op is the corresponding Python operator for op.\nfunc (obj *Base) RichCompareBool(obj2 *Base, op Op) (bool, error) {\n\tret := C.PyObject_RichCompareBool(obj.c(), obj2.c(), C.int(op))\n\treturn int2BoolErr(ret)\n}\n\n// PyObject_Cmp : Thanks to multiple return values, we don't need this function\n// to be available in Go.\n\n// Compare returns the result of comparing \"obj\" and \"obj2\".  This is equivalent\n// to the Python \"cmp(obj, obj2)\".\nfunc (obj *Base) Compare(obj2 *Base) (int, error) {\n\tret := C.PyObject_Compare(obj.c(), obj2.c())\n\treturn int(ret), exception()\n}\n\n// Repr returns a String representation of \"obj\".  This is equivalent to the\n// Python \"repr(obj)\".\n//\n// Return value: New Reference.\nfunc (obj *Base) Repr() (*Base, error) {\n\tret := C.PyObject_Repr(obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// Str returns a String representation of \"obj\".  This is equivalent to the\n// Python \"str(obj)\".\n//\n// Return value: New Reference.\nfunc (obj *Base) Str() (*Base, error) {\n\tret := C.PyObject_Str(obj.c())\n\treturn obj2ObjErr(ret)\n}\n\nfunc (obj *Base) String() string {\n\tif v, ok := AsString(obj); ok {\n\t\treturn v.String()\n\t}\n\tret := C.PyObject_Str(obj.c())\n\tif ret == nil {\n\t\treturn \"<nil>\"\n\t}\n\tdefer C.decref(ret)\n\treturn ((*String)(unsafe.Pointer(ret))).String()\n}\n\n// Bytes returns a Bytes representation of \"obj\".  This is equivalent to the\n// Python \"bytes(obj)\".  In Python 2.x this method is identical to Str().\n//\n// Return value: New Reference.\nfunc (obj *Base) Bytes() (*Base, error) {\n\tret := C.PyObject_Bytes(obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// PyObject_Unicode : TODO\n\n// IsInstance returns true if \"obj\" is an instance of \"cls\", false otherwise.\n// If \"cls\" is a Type instead of a class, then true will be return if \"obj\" is\n// of that type.  If \"cls\" is a Tuple then true will be returned if \"obj\" is an\n// instance of any of the Objects in the tuple.  This is equivalent to the\n// Python \"isinstance(obj, cls)\".\nfunc (obj *Base) IsInstance(cls *Base) (bool, error) {\n\tret := C.PyObject_IsInstance(obj.c(), cls.c())\n\treturn int2BoolErr(ret)\n}\n\n// IsSubclass retuns true if \"obj\" is a Subclass of \"cls\", false otherwise.  If\n// \"cls\" is a Tuple, then true is returned if \"obj\" is a Subclass of any member\n// of \"cls\".  This is equivalent to the Python \"issubclass(obj, cls)\".\nfunc (obj *Base) IsSubclass(cls *Base) (bool, error) {\n\tret := C.PyObject_IsSubclass(obj.c(), cls.c())\n\treturn int2BoolErr(ret)\n}\n\n// Call calls obj with the given args and kwds.  kwds may be nil, args may not\n// (an empty Tuple must be used if no arguments are wanted).  Returns the result\n// of the call, or an Error on failure.  This is equivalent to\n// \"obj(*args, **kwds)\" in Python.\n//\n// Return value: New Reference.\nfunc (obj *Base) Call(args *Tuple, kwds *Dict) (*Base, error) {\n\tret := C.PyObject_Call(obj.c(), args.c(), kwds.c())\n\treturn obj2ObjErr(ret)\n}\n\n// CallObject calls obj with the given args.  args may be nil.  Returns the\n// result of the call, or an Error on failure.  This is equivalent to\n// \"obj(*args)\" in Python.\n//\n// Return value: New Reference.\nfunc (obj *Base) CallObject(args *Tuple) (*Base, error) {\n\tvar a *C.PyObject = nil\n\tif args != nil {\n\t\ta = args.c()\n\t}\n\tret := C.PyObject_CallObject(obj.c(), a)\n\treturn obj2ObjErr(ret)\n}\n\nfunc (obj *Base) CallMethodObject(name string, args *Tuple) (*Base, error) {\n\tcname := C.CString(name)\n\tdefer C.free(unsafe.Pointer(cname))\n\n\tf := C.PyObject_GetAttrString(obj.c(), cname)\n\tif f == nil {\n\t\treturn nil, AttributeError.Err(name)\n\t}\n\tdefer C.decref(f)\n\n\tif C.PyCallable_Check(f) == 0 {\n\t\treturn nil, TypeError.Err(\"attribute of type '%s' is not callable\", name)\n\t}\n\n\tret := C.PyObject_CallObject(f, args.c())\n\treturn obj2ObjErr(ret)\n}\n\nfunc (obj *Base) CallObjArgs(args ...*Base) (*Base, error) {\n\targs1 := PackTuple(args...)\n\tdefer args1.Decref()\n\treturn obj.CallObject(args1)\n}\n\nfunc (obj *Base) CallMethodObjArgs(name string, args ...*Base) (*Base, error) {\n\targs1 := PackTuple(args...)\n\tdefer args1.Decref()\n\treturn obj.CallMethodObject(name, args1)\n}\n\n// PyObject_Hash : TODO\n\n// PyObject_HashNotImplement : This is an internal function, that we probably\n// don't need to export.\n\n// Length returns the length of the Object.  This is equivalent to the Python\n// \"len(obj)\".\nfunc (obj *Base) Length() (int64, error) {\n\tret := C.PyObject_Length(obj.c())\n\treturn int64(ret), exception()\n}\n\n// Size returns the length of the Object.  This is equivalent to the Python\n// \"len(obj)\".\nfunc (obj *Base) Size() (int64, error) {\n\tret := C.PyObject_Size(obj.c())\n\treturn int64(ret), exception()\n}\n\n// GetItem returns the element of \"obj\" corresponding to \"key\".  This is\n// equivalent to the Python \"obj[key]\".\n//\n// Return value: New Reference.\nfunc (obj *Base) GetItem(key *Base) (*Base, error) {\n\tret := C.PyObject_GetItem(obj.c(), key.c())\n\treturn obj2ObjErr(ret)\n}\n\n// SetItem sets the element of \"obj\" corresponding to \"key\" to \"value\".  This is\n// equivalent to the Python \"obj[key] = value\".\nfunc (obj *Base) SetItem(key, value *Base) error {\n\tret := C.PyObject_SetItem(obj.c(), key.c(), value.c())\n\treturn int2Err(ret)\n}\n\n// DelItem deletes the element from \"obj\" that corresponds to \"key\".  This is\n// equivalent to the Python \"del obj[key]\".\nfunc (obj *Base) DelItem(key *Base) error {\n\tret := C.PyObject_DelItem(obj.c(), key.c())\n\treturn int2Err(ret)\n}\n\n// PyObject_AsFileDescriptor : TODO\n\nfunc (obj *Base) Dir() (*Base, error) {\n\tret := C.PyObject_Dir(obj.c())\n\treturn obj2ObjErr(ret)\n}\n\n// PyObject_GetIter : TODO\n\n"
  },
  {
    "path": "object_test.go",
    "content": "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 v.String() != \"Hello!\" {\n\t\t\tt.Fatal(\"NewString failed\")\n\t\t}\n\t}\n\t{\n\t\tv := NewInt(1)\n\t\tdefer v.Decref()\n\n\t\tif v.String() != \"1\" {\n\t\t\tt.Fatal(\"NewInt failed\")\n\t\t}\n\t}\n\t{\n\t\tv1 := NewInt(1)\n\t\tdefer v1.Decref()\n\n\t\tv2 := NewString(\"Hello!\")\n\t\tdefer v2.Decref()\n\n\t\tv := PackTuple(v1.Obj(), v2.Obj())\n\t\tdefer v.Decref()\n\n\t\tif v.String() != \"(1, 'Hello!')\" {\n\t\t\tt.Fatal(\"NewTuple failed:\", v.String())\n\t\t}\n\t}\n\t{\n\t\tv1 := NewInt(1)\n\t\tdefer v1.Decref()\n\n\t\tv2 := NewString(\"Hello!\")\n\t\tdefer v2.Decref()\n\n\t\tv := NewDict()\n\t\tdefer v.Decref()\n\n\t\tv.SetItem(v1.Obj(), v2.Obj())\n\n\t\tif v.String() != \"{1: 'Hello!'}\" {\n\t\t\tt.Fatal(\"NewDict failed:\", v.String())\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "python.go",
    "content": "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_EnterRecursiveCall(w);\n}\n\nstatic inline void leaveRecursive() {\n\tPy_LeaveRecursiveCall();\n}\n*/\nimport \"C\"\nimport \"unsafe\"\n\nfunc init() {\n\tC.Py_Initialize()\n}\n\nfunc Initialize() {\n\tC.Py_Initialize()\n}\n\nfunc InitializeEx(initsigs bool) {\n\tif initsigs {\n\t\tC.Py_InitializeEx(1)\n\t} else {\n\t\tC.Py_InitializeEx(0)\n\t}\n}\n\nfunc Finalize() {\n\tC.Py_Finalize()\n}\n\nfunc AddToPath(dir string) {\n\tp := C.CString(\"path\")\n\tdefer C.free(unsafe.Pointer(p))\n\n\tsys_path := C.PySys_GetObject(p)\n\tif sys_path == nil {\n\t\treturn\n\t}\n\n\ts := C.CString(dir)\n\tdefer C.free(unsafe.Pointer(s))\n\n\tpDir := C.PyString_FromString(s)\n\tif pDir == nil {\n\t\treturn\n\t}\n\n\tC.PyList_Append(sys_path, pDir)\n}\n\nfunc Main(args []string) int {\n\targv := make([]*C.char, len(args))\n\n\tfor i, arg := range args {\n\t\targv[i] = C.CString(arg)\n\t\tdefer C.free(unsafe.Pointer(argv[i]))\n\t}\n\n\treturn int(C.Py_Main(C.int(len(argv)), &argv[0]))\n}\n\n// EnterRecusiveCall marks a point where a recursive Go-level call is about to\n// be performed.  It returns true if the recursive call is permitted, otherwise\n// a Python exception is set and false is returned.  where is a string that will\n// be appended to the RuntimeError set if the recursion limit has been exceeded\n// (e.g. \" in instance check\").  This function needs to be called if the\n// recursive function may not invoke Python code (which automatically tracks\n// recursion depth).\nfunc EnterRecursiveCall(where string) bool {\n\ts := C.CString(where)\n\tdefer C.free(unsafe.Pointer(s))\n\treturn C.enterRecursive(s) == 0\n}\n\n// LeaveRecursiveCall must be called after a recursive call that was indicated\n// by EnterRecursiveCall.\nfunc LeaveRecursiveCall() {\n\tC.leaveRecursive()\n}\n"
  },
  {
    "path": "pyutil/call.go",
    "content": "package pyutil\n\nimport (\n\t\"syscall\"\n\t\"github.com/qiniu/py\"\n\t\"github.com/qiniu/errors\"\n)\n\n// ------------------------------------------------------------------------------------------\n\nfunc PackEx(cfg *Config, args ...interface{}) (ret *py.Tuple, err error) {\n\n\targs1 := py.NewTuple(len(args))\n\n\tfor i, arg := range args {\n\t\tv1, ok1 := NewVarEx(arg, cfg)\n\t\tif !ok1 {\n\t\t\targs1.Decref()\n\t\t\terr = errors.Info(syscall.EINVAL, \"pyutil.Pack\", i+1, arg).Detail(err)\n\t\t\treturn\n\t\t}\n\t\targs1.SetItem(i, v1)\n\t}\n\treturn args1, nil\n}\n\nfunc Pack(args ...interface{}) (ret *py.Tuple, err error) {\n\n\treturn PackEx(DefaultConfig, args...)\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc CallEx(cfg *Config, fn *py.Base, args ...interface{}) (ret *py.Base, err error) {\n\n\targs1, err := PackEx(cfg, args...)\n\tif err != nil {\n\t\terr = errors.Info(syscall.EINVAL, \"pyutil.Call\").Detail(err)\n\t\treturn\n\t}\n\tdefer args1.Decref()\n\n\treturn fn.CallObject(args1)\n}\n\nfunc Call(fn *py.Base, args ...interface{}) (*py.Base, error) {\n\n\treturn CallEx(DefaultConfig, fn, args...)\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc CallMethodEx(cfg *Config, self *py.Base, method string, args ...interface{}) (ret *py.Base, err error) {\n\n\targs1, err := PackEx(cfg, args...)\n\tif err != nil {\n\t\terr = errors.Info(syscall.EINVAL, \"pyutil.Call\").Detail(err)\n\t\treturn\n\t}\n\tdefer args1.Decref()\n\n\treturn self.CallMethodObject(method, args1)\n}\n\nfunc CallMethod(self *py.Base, method string, args ...interface{}) (ret *py.Base, err error) {\n\n\treturn CallMethodEx(DefaultConfig, self, method, args...)\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc NewInstanceEx(cfg *Config, typ *py.Class, args ...interface{}) (ret *py.Base, err error) {\n\n\targs1, err := PackEx(cfg, args...)\n\tif err != nil {\n\t\terr = errors.Info(syscall.EINVAL, \"pyutil.NewInstance\").Detail(err)\n\t\treturn\n\t}\n\tdefer args1.Decref()\n\n\treturn typ.New(args1, nil)\n}\n\nfunc NewInstance(typ *py.Class, args ...interface{}) (ret *py.Base, err error) {\n\n\treturn NewInstanceEx(DefaultConfig, typ, args...)\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc NewEx(cfg *Config, mod *py.Base, clsname string, args ...interface{}) (ret *py.Base, err error) {\n\n\to, err := mod.GetAttrString(clsname)\n\tif err != nil {\n\t\terr = errors.Info(err, \"pyutil.New\", clsname).Detail(err)\n\t\treturn\n\t}\n\tdefer o.Decref()\n\n\tty, ok := py.AsClass(o)\n\tif !ok {\n\t\terr = errors.Info(syscall.EINVAL, \"pyutil.New\", o.String(), \"is not a class\")\n\t\treturn\n\t}\n\n\treturn NewInstanceEx(cfg, ty, args...)\n}\n\nfunc New(mod *py.Base, clsname string, args ...interface{}) (ret *py.Base, err error) {\n\n\treturn NewEx(DefaultConfig, mod, clsname, args...)\n}\n\n// ------------------------------------------------------------------------------------------\n\n"
  },
  {
    "path": "pyutil/call_test.go",
    "content": "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 moduleCase struct {\n\texp string\n\tname, ret, tbl string\n}\n\nvar g_moduleCases = []moduleCase{\n\t{`\nclass Plugin:\n\tdef init(self, cate):\n\t\tself.tbl = \"dn_5m\" + cate\n`, \"foo\", \"None\", \"dn_5m_stage\"},\n}\n\nfunc TestCall(t *testing.T) {\n\n\tlog.SetOutputLevel(0)\n\n\tfor _, c := range g_moduleCases {\n\t\tcode, err := py.Compile(c.exp, \"\", py.FileInput)\n\t\tif err != nil {\n\t\t\tt.Fatal(\"Compile failed:\", err)\n\t\t}\n\t\tdefer code.Decref()\n\n\t\tmod, err := py.ExecCodeModule(c.name, code.Obj())\n\t\tif err != nil {\n\t\t\tt.Fatal(\"ExecCodeModule failed:\", err)\n\t\t}\n\t\tdefer mod.Decref()\n\n\t\tplg, err := New(mod.Obj(), \"Plugin\")\n\t\tif err != nil {\n\t\t\tt.Fatal(\"NewPlugin failed:\", errors.Detail(err))\n\t\t}\n\n\t\tret, err := CallMethod(plg, \"init\", \"_stage\")\n\t\tif err != nil {\n\t\t\tt.Fatal(\"CallMethod failed:\", err)\n\t\t}\n\t\tdefer ret.Decref()\n\n\t\tif ret.String() != c.ret {\n\t\t\tt.Fatal(\"CallMethod ret:\", ret.String(), c.ret)\n\t\t}\n\n\t\ttbl, _ := plg.GetAttrString(\"tbl\")\n\t\tif tbl.String() != c.tbl {\n\t\t\tt.Fatal(\"mod.GetAttrString('tbl') ret:\", tbl.String(), c.tbl)\n\t\t}\n\t}\n}\n\n"
  },
  {
    "path": "pyutil/var.go",
    "content": "package pyutil\n\nimport (\n\t\"strings\"\n\t\"reflect\"\n\t\"github.com/qiniu/py\"\n)\n\n// ------------------------------------------------------------------------------------------\n\ntype Config struct {\n\tCate string\n\tSliceAsList bool\n}\n\nvar DefaultConfig = &Config {\n\tCate: \"json\",\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc tagName(tag string) (string) {\n\tif idx := strings.Index(tag, \",\"); idx != -1 {\n\t\treturn tag[:idx]\n\t}\n\treturn tag\n}\n\nfunc newStruct(sv reflect.Value, cfg *Config) (ret *py.Base, ok bool) {\n\n\tdict := py.NewDict()\n\n\tst := sv.Type()\n\tfor i := 0; i < sv.NumField(); i++ {\n\t\tsf := st.Field(i)\n\t\ttag := sf.Tag.Get(cfg.Cate)\n\t\tif tag == \"\" {\n\t\t\treturn nil, false\n\t\t}\n\t\tname := tagName(tag)\n\t\tval := sv.Field(i)\n\t\tval1, ok1 := NewVarEx(val.Interface(), cfg)\n\t\tif !ok1 {\n\t\t\tdict.Decref()\n\t\t\treturn nil, false\n\t\t}\n\t\tdict.SetItemString(name, val1)\n\t\tval1.Decref()\n\t}\n\n\treturn dict.Obj(), true\n}\n\nfunc newMap(v reflect.Value, cfg *Config) (ret *py.Base, ok bool) {\n\n\tdict := py.NewDict()\n\n\tkeys := v.MapKeys()\n\tfor _, key := range keys {\n\t\tkey1, ok1 := NewVarEx(key.Interface(), cfg)\n\t\tif !ok1 {\n\t\t\tdict.Decref()\n\t\t\treturn nil, false\n\t\t}\n\t\tval1, ok1 := NewVarEx(v.MapIndex(key).Interface(), cfg)\n\t\tif !ok1 {\n\t\t\tkey1.Decref()\n\t\t\tdict.Decref()\n\t\t\treturn nil, false\n\t\t}\n\t\tdict.SetItem(key1, val1)\n\t\tkey1.Decref()\n\t\tval1.Decref()\n\t}\n\n\treturn dict.Obj(), true\n}\n\nfunc newComplex(val reflect.Value, cfg *Config) (ret *py.Base, ok bool) {\n\nretry:\n\tswitch val.Kind() {\n\tcase reflect.Struct:\n\t\treturn newStruct(val, cfg)\n\tcase reflect.Map:\n\t\treturn newMap(val, cfg)\n\tcase reflect.Ptr, reflect.Interface:\n\t\tval = val.Elem()\n\t\tgoto retry\n\t}\n\treturn nil, false\n}\n\n// ------------------------------------------------------------------------------------------\n\nfunc NewVarEx(val interface{}, cfg *Config) (ret *py.Base, ok bool) {\n\n\tswitch v := val.(type) {\n\tcase int:\n\t\treturn py.NewInt(v).Obj(), true\n\tcase int64:\n\t\treturn py.NewLong(v).Obj(), true\n\tcase string:\n\t\treturn py.NewString(v).Obj(), true\n\t}\n\treturn newComplex(reflect.ValueOf(val), cfg)\n}\n\nfunc NewVar(val interface{}) (ret *py.Base, ok bool) {\n\n\treturn NewVarEx(val, DefaultConfig)\n}\n\n// ------------------------------------------------------------------------------------------\n"
  },
  {
    "path": "pyutil/var_test.go",
    "content": "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}\n\nfunc Test(t *testing.T) {\n\n\t{\n\t\tval, ok := NewVar(1)\n\t\tif !ok {\n\t\t\tt.Fatal(\"NewVar failed\")\n\t\t}\n\t\tif v, ok := py.AsInt(val); !ok || v.Int() != 1 {\n\t\t\tt.Fatal(\"NewVar failed:\", val)\n\t\t}\n\t}\n\t{\n\t\tval, ok := NewVar(int64(1))\n\t\tif !ok {\n\t\t\tt.Fatal(\"NewVar failed\")\n\t\t}\n\t\tif v, ok := py.AsLong(val); !ok || v.Long() != 1 {\n\t\t\tt.Fatal(\"NewVar failed:\", val)\n\t\t}\n\t}\n\t{\n\t\tval, ok := NewVar(\"Hello\")\n\t\tif !ok {\n\t\t\tt.Fatal(\"NewVar failed\")\n\t\t}\n\t\tif v, ok := py.AsString(val); !ok || v.String() != \"Hello\" {\n\t\t\tt.Fatal(\"NewVar failed:\", val)\n\t\t}\n\t}\n\t{\n\t\tfoo := &Foo{\n\t\t\tA: 1, B: \"Hello\",\n\t\t}\n\t\tval, ok := NewVar(foo)\n\t\tif !ok {\n\t\t\tt.Fatal(\"NewVar failed\")\n\t\t}\n\t\tif v, ok := py.AsDict(val); !ok || !checkFoo(v, t) {\n\t\t\tt.Fatal(\"NewVar failed:\", val)\n\t\t}\n\t}\n\t{\n\t\tfoo := map[string]interface{}{\n\t\t\t\"a\": 1, \"b\": \"Hello\",\n\t\t}\n\t\tval, ok := NewVar(foo)\n\t\tif !ok {\n\t\t\tt.Fatal(\"NewVar failed\")\n\t\t}\n\t\tif v, ok := py.AsDict(val); !ok || !checkFoo(v, t) {\n\t\t\tt.Fatal(\"NewVar failed:\", val)\n\t\t}\n\t}\n}\n\nfunc checkFoo(val *py.Dict, t *testing.T) bool {\n\n\ta := val.GetItemString(\"a\")\n\tif a == nil {\n\t\tt.Fatal(\"GetItemString a failed\")\n\t\treturn false\n\t}\n\tif v, ok := py.AsInt(a); !ok || v.Int() != 1 {\n\t\tt.Fatal(\"GetItemString a failed\")\n\t}\n\n\tb := val.GetItemString(\"b\")\n\tif b == nil {\n\t\tt.Fatal(\"GetItemString b failed\")\n\t\treturn false\n\t}\n\tif v, ok := py.AsString(b); !ok || v.String() != \"Hello\" {\n\t\tt.Fatal(\"GetItemString b failed\")\n\t}\n\treturn true\n}\n\n"
  },
  {
    "path": "string.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int stringCheck(PyObject *o) { return PyString_Check(o); }\nimport \"C\"\nimport \"unsafe\"\n\ntype String struct {\n\tBase\n\to C.PyStringObject\n}\n\n// StringType is the Type object that represents the String type.\nvar StringType = (*Type)(unsafe.Pointer(&C.PyString_Type))\n\nfunc newString(obj *C.PyObject) *String {\n\treturn (*String)(unsafe.Pointer(obj))\n}\n\nfunc NewString(s string) *String {\n\tcs := C.CString(s)\n\tdefer C.free(unsafe.Pointer(cs))\n\tret := C.PyString_FromString(cs)\n\treturn newString(ret)\n}\n\nfunc AsString(o *Base) (v *String, ok bool) {\n\tif ok = C.stringCheck(o.c()) != 0; ok {\n\t\tv = newString(o.c())\n\t}\n\treturn\n}\n\nfunc (s *String) String() string {\n\tif s == nil {\n\t\treturn \"<nil>\"\n\t}\n\tret := C.PyString_AsString(s.c())\n\treturn C.GoString(ret)\n}\n\nfunc (s *String) Format(args *Tuple) (*String, error) {\n\tret := C.PyString_Format(s.c(), args.c())\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newString(ret), nil\n}\n"
  },
  {
    "path": "tuple.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int tupleCheckE(PyObject *o) { return PyTuple_CheckExact(o); }\n// static inline int tupleCheck(PyObject *o) { return PyTuple_Check(o); }\n// static inline size_t tupleItemSize() { return sizeof(PyObject *); }\nimport \"C\"\nimport \"unsafe\"\n\ntype Tuple struct {\n\tBase\n\to C.PyTupleObject\n}\n\n// TupleType is the Type object that represents the Tuple type.\nvar TupleType = (*Type)(unsafe.Pointer(&C.PyTuple_Type))\n\nfunc newTuple(obj *C.PyObject) *Tuple {\n\treturn (*Tuple)(unsafe.Pointer(obj))\n}\n\n// NewTuple returns a new *Tuple of the specified size.  However the entries are\n// all set to NULL, so the tuple should not be shared, especially with Python\n// code, until the entries have all been set.\n//\n// Return value: New Reference.\nfunc NewTuple(size int) *Tuple {\n\tret := C.PyTuple_New(C.Py_ssize_t(size))\n\treturn newTuple(ret)\n}\n\nfunc AsTuple(o *Base) (v *Tuple, ok bool) {\n\tif ok = C.tupleCheck(o.c()) != 0; ok {\n\t\tv = newTuple(o.c())\n\t}\n\treturn\n}\n\n// PackTuple returns a new *Tuple which contains the arguments.  This tuple is\n// ready to use.\n//\n// Return value: New Reference.\nfunc PackTuple(items ...*Base) *Tuple {\n\tret := C.PyTuple_New(C.Py_ssize_t(len(items)))\n\n\t// Since the ob_item array has a size of 1, Go won't let us index more than\n\t// a single entry, and if we try and use our own local type definition with\n\t// a flexible array member then cgo converts it to [0]byte which is even\n\t// less useful.  So, we resort to pointer manipulation - which is\n\t// unfortunate, as it's messy in Go.\n\n\t// base is a pointer to the first item in the array of PyObject pointers.\n\t// step is the size of a PyObject * (i.e. the number of bytes we need to add\n\t// to get to the next item).\n\tbase := unsafe.Pointer(&(*C.PyTupleObject)(unsafe.Pointer(ret)).ob_item[0])\n\tstep := uintptr(C.tupleItemSize())\n\n\tfor _, item := range items {\n\t\titem.Incref()\n\t\t*(**C.PyObject)(base) = item.c()\n\n\t\t// Move base to point to the next item, by incrementing by step bytes\n\t\tbase = unsafe.Pointer(uintptr(base) + step)\n\t}\n\treturn newTuple(ret)\n}\n\nfunc (t *Tuple) CheckExact() bool {\n\tret := C.tupleCheckE(t.c())\n\tif int(ret) != 0 {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (t *Tuple) Size() int {\n\tret := C.PyTuple_Size(t.c())\n\tif ret < 0 {\n\t\tpanic(exception())\n\t}\n\treturn int(ret)\n}\n\n// Return the object at position pos in the tuple pointed to by p. If pos is out of bounds, \n// return NULL and sets an IndexError exception.\n//\n// Return value: Borrowed reference.\nfunc (t *Tuple) GetItem(pos int) (*Base, error) {\n\tret := C.PyTuple_GetItem(t.c(), C.Py_ssize_t(pos))\n\treturn obj2ObjErr(ret)\n}\n\nfunc (t *Tuple) GetSlice(low, high int) (*Tuple, error) {\n\tret := C.PyTuple_GetSlice(t.c(), C.Py_ssize_t(low), C.Py_ssize_t(high))\n\tif ret == nil {\n\t\treturn nil, exception()\n\t}\n\treturn newTuple(ret), nil\n}\n\n// Insert a reference to object o at position pos of the tuple pointed to by p. Return 0 on success.\n// Note This function “steals” a reference to o.\nfunc (t *Tuple) SetItem(pos int, obj *Base) error {\n\tret := C.PyTuple_SetItem(t.c(), C.Py_ssize_t(pos), obj.c())\n\treturn int2Err(ret)\n}\n\n// _PyTuple_Resize\n\n// PyTuple_ClearFreeList()\n\nfunc (t *Tuple) Slice() []*Base {\n\tl := t.Size()\n\ts := make([]*Base, l)\n\tfor i := 0; i < l; i++ {\n\t\to, err := t.GetItem(i)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\ts[i] = o\n\t}\n\treturn s\n}\n\n"
  },
  {
    "path": "type.go",
    "content": "package py\n\n// #include <Python.h>\n// static inline int typeCheck(PyObject *o) { return PyType_Check(o); }\n// static inline int typeCheckE(PyObject *o) { return PyType_CheckExact(o); }\n// static inline PyObject* typeAlloc(PyObject *t, Py_ssize_t n) {\n//    return ((PyTypeObject*)t)->tp_alloc((PyTypeObject *)t, n);\n// }\n// static inline int typeInit(PyObject *t, PyObject *o, PyObject *a, PyObject *k) {\n//    return ((PyTypeObject*)t)->tp_init(o, a, k);\n// }\n// static inline PyObject* typeNew(PyObject *t, PyObject *a, PyObject *k) {\n//    return ((PyTypeObject*)t)->tp_new((PyTypeObject*)t, a, k);\n// }\nimport \"C\"\nimport \"unsafe\"\n\ntype Type struct {\n\tBase\n\to C.PyTypeObject\n}\n\n// TypeType is the Type object that represents the Type type.\nvar TypeType = (*Type)(unsafe.Pointer(&C.PyType_Type))\n\nfunc newType(obj *C.PyObject) *Type {\n\treturn (*Type)(unsafe.Pointer(obj))\n}\n\nfunc AsType(o *Base) (v *Type, ok bool) {\n\tif ok = C.typeCheck(o.c()) != 0; ok {\n\t\tv = newType(o.c())\n\t}\n\treturn\n}\n\nfunc (t *Type) NewNoArgs() (ret *Base, err error) {\n\targs := NewTuple(0)\n\tdefer args.Decref()\n\treturn t.New(args, nil)\n}\n\nfunc (t *Type) New(args *Tuple, kw *Dict) (ret *Base, err error) {\n\tret1 := C.typeNew(t.c(), args.c(), kw.c())\n\treturn obj2ObjErr(ret1)\n}\n\nfunc (t *Type) NewObjArgs(args ...*Base) (ret *Base, err error) {\n\targs1 := PackTuple(args...)\n\tdefer args1.Decref()\n\treturn t.New(args1, nil)\n}\n\nfunc (t *Type) Alloc(n int64) (*Base, error) {\n\tret := C.typeAlloc(t.c(), C.Py_ssize_t(n))\n\treturn obj2ObjErr(ret)\n}\n\nfunc (t *Type) Init(obj *Base, args *Tuple, kw *Dict) error {\n\tret := C.typeInit(t.c(), obj.c(), args.c(), kw.c())\n\tif ret < 0 {\n\t\treturn exception()\n\t}\n\treturn nil\n}\n\n// CheckExact returns true when \"t\" is an actual Type object, and not some form\n// of subclass.\nfunc (t *Type) CheckExact() bool {\n\treturn C.typeCheckE(t.c()) == 1\n}\n\n// PyType_ClearCache : TODO - ???\n\n// Modified should be called after the attributes or base class of a Type have\n// been changed.\nfunc (t *Type) Modified() {\n\tC.PyType_Modified(&t.o)\n}\n\n// HasFeature returns true when \"t\" has the feature in question.\nfunc (t *Type) HasFeature(feature uint32) bool {\n\treturn (t.o.tp_flags & C.long(feature)) != 0\n}\n\n// IsGc returns true if the type \"t\" supports Cyclic Garbage Collection.\nfunc (t *Type) IsGc() bool {\n\treturn t.HasFeature(C.Py_TPFLAGS_HAVE_GC)\n}\n\n// IsSubtype returns true if \"t\" is a subclass of \"t2\".\nfunc (t *Type) IsSubtype(t2 *Type) bool {\n\treturn C.PyType_IsSubtype(&t.o, &t2.o) == 1\n}\n\n// PyType_GenericAlloc : This is an internal function, which we should not need\n// to expose.\n\n// PyType_GenericNew : Another internal function we don't need to expose.\n\n// PyType_Ready : This function is wrapped (along with a lot of other\n// functionality) in the Create method of the Class stuct.\n"
  }
]