primitive.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. package python
  2. // See:
  3. // https://docs.python.org/3/c-api/concrete.html
  4. import (
  5. "fmt"
  6. "unsafe"
  7. )
  8. /*
  9. #define PY_SSIZE_T_CLEAN
  10. #include <Python.h>
  11. */
  12. import "C"
  13. func NewPrimitiveReference(value interface{}) (*Reference, error) {
  14. if value == nil {
  15. return None, nil
  16. }
  17. switch value_ := value.(type) {
  18. case *Reference:
  19. return value_, nil
  20. case bool:
  21. if value_ {
  22. return True, nil
  23. } else {
  24. return False, nil
  25. }
  26. case int64:
  27. return NewLong(value_)
  28. case int32:
  29. return NewLong(int64(value_))
  30. case int8:
  31. return NewLong(int64(value_))
  32. case int:
  33. return NewLong(int64(value_))
  34. case float64:
  35. return NewFloat(value_)
  36. case float32:
  37. return NewFloat(float64(value_))
  38. case string:
  39. return NewUnicode(value_)
  40. case []interface{}:
  41. return NewList(value_...)
  42. case []byte:
  43. return NewBytes(value_)
  44. }
  45. return nil, fmt.Errorf("unsupported type: %s", value)
  46. }
  47. func (self *Reference) ToInterface(recurse int) (interface{}, error) {
  48. if self.IsLong() {
  49. return self.ToInt64()
  50. }
  51. if self.IsUnicode() {
  52. return self.ToString()
  53. }
  54. if self.IsBool() {
  55. return self.ToBool(), nil
  56. }
  57. if self.IsNone() {
  58. return nil, nil
  59. }
  60. if self.IsFloat() {
  61. return self.ToFloat64()
  62. }
  63. if self.IsBytes() {
  64. return self.ToBytes()
  65. }
  66. if self.IsByteArray() {
  67. return self.ByteArrayToBytes()
  68. }
  69. if self.IsDict() {
  70. if recurse <= 0 {
  71. return nil, fmt.Errorf("reached recursion limit")
  72. }
  73. mapValue := make(map[interface{}]interface{})
  74. dict, err := self.ToMap()
  75. if err != nil { return mapValue, err }
  76. errorNum := 0
  77. for key, val := range dict {
  78. keyValue, err1 := key.ToInterface(recurse-1)
  79. valValue, err2 := val.ToInterface(recurse-1)
  80. key.Release()
  81. val.Release()
  82. if err1 == nil && err2 == nil {
  83. mapValue[keyValue] = valValue
  84. } else {
  85. errorNum ++
  86. }
  87. }
  88. if errorNum > 0 {
  89. return mapValue, fmt.Errorf("failed to convert %d primitives from dictionary", errorNum)
  90. }
  91. return mapValue, nil
  92. }
  93. if self.IsList() {
  94. if recurse <= 0 {
  95. return nil, fmt.Errorf("reached recursion limit")
  96. }
  97. pyList, err := self.ToList()
  98. if err != nil { return nil, err }
  99. goList := make([]interface{}, len(pyList))
  100. errorNum := 0
  101. for i, item := range pyList {
  102. if goList[i], err = item.ToInterface(recurse-1); err != nil {
  103. errorNum ++
  104. }
  105. item.Release()
  106. }
  107. if errorNum > 0 {
  108. return goList, fmt.Errorf("failed to convert %d primitives from list", errorNum)
  109. }
  110. return goList, nil
  111. }
  112. return nil, fmt.Errorf("unsupported primitive: %s", self.String())
  113. }
  114. //
  115. // None
  116. //
  117. var None = NewReference(C.Py_None)
  118. //
  119. // Bool
  120. //
  121. var BoolType = NewType(&C.PyBool_Type)
  122. var True = NewReference(C.Py_True)
  123. var False = NewReference(C.Py_False)
  124. func (self *Reference) IsNone() bool {
  125. return self.Object == C.Py_None
  126. }
  127. func (self *Reference) IsBool() bool {
  128. return self.Type().IsSubtype(BoolType)
  129. }
  130. func (self *Reference) ToBool() bool {
  131. switch self.Object {
  132. case C.Py_True:
  133. return true
  134. case C.Py_False:
  135. return false
  136. }
  137. return false
  138. }
  139. //
  140. // Long
  141. //
  142. var LongType = NewType(&C.PyLong_Type)
  143. func NewLong(value int64) (*Reference, error) {
  144. if long := C.PyLong_FromLong(C.long(value)); long != nil {
  145. return NewReference(long), nil
  146. } else {
  147. return nil, GetError()
  148. }
  149. }
  150. func (self *Reference) IsLong() bool {
  151. // More efficient to use the flag
  152. return self.Type().HasFlag(C.Py_TPFLAGS_LONG_SUBCLASS)
  153. }
  154. func (self *Reference) ToInt64() (int64, error) {
  155. if long := C.PyLong_AsLongLong(self.Object); !HasException() {
  156. return int64(long), nil
  157. } else {
  158. return int64(long), GetError()
  159. }
  160. }
  161. //
  162. // Float
  163. //
  164. var FloatType = NewType(&C.PyFloat_Type)
  165. func NewFloat(value float64) (*Reference, error) {
  166. if float := C.PyFloat_FromDouble(C.double(value)); float != nil {
  167. return NewReference(float), nil
  168. } else {
  169. return nil, GetError()
  170. }
  171. }
  172. func (self *Reference) IsFloat() bool {
  173. return self.Type().IsSubtype(FloatType)
  174. }
  175. func (self *Reference) ToFloat64() (float64, error) {
  176. if double := C.PyFloat_AsDouble(self.Object); !HasException() {
  177. return float64(double), nil
  178. } else {
  179. return 0.0, GetError()
  180. }
  181. }
  182. //
  183. // Unicode
  184. //
  185. var UnicodeType = NewType(&C.PyUnicode_Type)
  186. func NewUnicode(value string) (*Reference, error) {
  187. value_ := C.CString(value)
  188. defer C.free(unsafe.Pointer(value_))
  189. if unicode := C.PyUnicode_FromString(value_); unicode != nil {
  190. return NewReference(unicode), nil
  191. } else {
  192. return nil, GetError()
  193. }
  194. }
  195. func (self *Reference) IsUnicode() bool {
  196. // More efficient to use the flag
  197. return self.Type().HasFlag(C.Py_TPFLAGS_UNICODE_SUBCLASS)
  198. }
  199. func (self *Reference) ToString() (string, error) {
  200. if utf8stringBytes := C.PyUnicode_AsUTF8String(self.Object); utf8stringBytes != nil {
  201. defer C.Py_DecRef(utf8stringBytes)
  202. if utf8string := C.PyBytes_AsString(utf8stringBytes); utf8string != nil {
  203. return C.GoString(utf8string), nil
  204. } else {
  205. return "", GetError()
  206. }
  207. } else {
  208. return "", GetError()
  209. }
  210. }
  211. //
  212. // Tuple
  213. //
  214. var TupleType = NewType(&C.PyTuple_Type)
  215. func NewTuple(items ...interface{}) (*Reference, error) {
  216. if tuple, err := NewTupleRaw(len(items)); err == nil {
  217. for index, item := range items {
  218. if item_, err := NewPrimitiveReference(item); err == nil {
  219. if err := tuple.SetTupleItem(index, item_); err != nil {
  220. return nil, err
  221. }
  222. } else {
  223. return nil, err
  224. }
  225. }
  226. return tuple, nil
  227. } else {
  228. return nil, GetError()
  229. }
  230. }
  231. func NewTupleRaw(size int) (*Reference, error) {
  232. if tuple := C.PyTuple_New(C.long(size)); tuple != nil {
  233. return NewReference(tuple), nil
  234. } else {
  235. return nil, GetError()
  236. }
  237. }
  238. func (self *Reference) IsTuple() bool {
  239. // More efficient to use the flag
  240. return self.Type().HasFlag(C.Py_TPFLAGS_TUPLE_SUBCLASS)
  241. }
  242. func (self *Reference) SetTupleItem(index int, item *Reference) error {
  243. if C.PyTuple_SetItem(self.Object, C.long(index), item.Object) == 0 {
  244. return nil
  245. } else {
  246. return GetError()
  247. }
  248. }
  249. //
  250. // List
  251. //
  252. var ListType = NewType(&C.PyList_Type)
  253. func NewList(items ...interface{}) (*Reference, error) {
  254. if list, err := NewListRaw(len(items)); err == nil {
  255. for index, item := range items {
  256. if item_, err := NewPrimitiveReference(item); err == nil {
  257. if err := list.SetListItem(index, item_); err != nil {
  258. return nil, err
  259. }
  260. } else {
  261. return nil, err
  262. }
  263. }
  264. return list, nil
  265. } else {
  266. return nil, GetError()
  267. }
  268. }
  269. func NewListRaw(size int) (*Reference, error) {
  270. if list := C.PyList_New(C.long(size)); list != nil {
  271. return NewReference(list), nil
  272. } else {
  273. return nil, GetError()
  274. }
  275. }
  276. func (self *Reference) IsList() bool {
  277. // More efficient to use the flag
  278. return self.Type().HasFlag(C.Py_TPFLAGS_LIST_SUBCLASS)
  279. }
  280. func (self *Reference) SetListItem(index int, item *Reference) error {
  281. if C.PyList_SetItem(self.Object, C.long(index), item.Object) == 0 {
  282. return nil
  283. } else {
  284. return GetError()
  285. }
  286. }
  287. func (self *Reference) ToList() ([]*Reference, error) {
  288. var listLen int
  289. if listLen = int(C.PyList_Size(self.Object)); HasException() {
  290. return nil, GetError()
  291. }
  292. goList := make([]*Reference, listLen)
  293. for i := 0; i < listLen; i++ {
  294. index := C.long(int64(i))
  295. if item := C.PyList_GetItem(self.Object, index); item != nil {
  296. goList[i] = NewReference(item)
  297. }
  298. }
  299. return goList, nil
  300. }
  301. func (self *Reference) Iteratable() bool {
  302. return int(C.PyIter_Check(self.Object)) == 1
  303. }
  304. func (self *Reference) Iterate(next <-chan bool) (<-chan *Reference, error) {
  305. iterator := C.PyObject_GetIter(self.Object)
  306. if iterator == nil || HasException() {
  307. return nil, GetError()
  308. }
  309. ch := make(chan *Reference, 1)
  310. go func() {
  311. defer close(ch)
  312. defer C.Py_DecRef(iterator)
  313. forLoop:
  314. for ;; {
  315. if <- next {
  316. item := C.PyIter_Next(iterator);
  317. if item == nil { break }
  318. pyItem := NewReference(item)
  319. select {
  320. case ch <- pyItem:
  321. default:
  322. pyItem.Release()
  323. break forLoop
  324. }
  325. } else {
  326. break
  327. }
  328. }
  329. }()
  330. return ch, nil
  331. }
  332. //
  333. // Dict
  334. //
  335. var DictType = NewType(&C.PyDict_Type)
  336. func NewDict() (*Reference, error) {
  337. if dict := C.PyDict_New(); dict != nil {
  338. return NewReference(dict), nil
  339. } else {
  340. return nil, GetError()
  341. }
  342. }
  343. func (self *Reference) IsDict() bool {
  344. // More efficient to use the flag
  345. return self.Type().HasFlag(C.Py_TPFLAGS_DICT_SUBCLASS)
  346. }
  347. func (self *Reference) SetDictItem(key *Reference, value *Reference) error {
  348. if C.PyDict_SetItem(self.Object, key.Object, value.Object) == 0 {
  349. return nil
  350. } else {
  351. return GetError()
  352. }
  353. }
  354. func (self *Reference) DictContains(key *Reference) (bool, error) {
  355. res := C.PyDict_Contains(self.Object, key.Object)
  356. if res == -1 {
  357. return false, GetError()
  358. }
  359. return res == 1, nil
  360. }
  361. func (self *Reference) DictContainsString(key string) (bool, error) {
  362. keyObj, err := NewUnicode(key)
  363. if err != nil {
  364. return false, err
  365. }
  366. defer keyObj.Release()
  367. res := C.PyDict_Contains(self.Object, keyObj.Object)
  368. if res == -1 {
  369. return false, GetError()
  370. }
  371. return res == 1, nil
  372. }
  373. func (self *Reference) GetDictItemString(key string) *Reference {
  374. value_ := C.CString(key)
  375. defer C.free(unsafe.Pointer(value_))
  376. if obj := C.PyDict_GetItemString(self.Object, value_); obj != nil {
  377. return NewReference(obj)
  378. }
  379. return nil
  380. }
  381. func (self *Reference) GetDictItem(key *Reference) *Reference {
  382. if obj := C.PyDict_GetItem(self.Object, key.Object); obj != nil {
  383. return NewReference(obj)
  384. }
  385. return nil
  386. }
  387. func (self *Reference) DeleteDictItem(key *Reference) error {
  388. if ret := C.PyDict_DelItem(self.Object, key.Object); ret != 0 {
  389. return GetError()
  390. }
  391. return nil
  392. }
  393. func (self *Reference) DeleteDictItemString(key string) error {
  394. value_ := C.CString(key)
  395. defer C.free(unsafe.Pointer(value_))
  396. if ret := C.PyDict_DelItemString(self.Object, value_); ret != 0 {
  397. return GetError()
  398. }
  399. return nil
  400. }
  401. func (self *Reference) ToMap() (map[*Reference]*Reference, error) {
  402. keys := C.PyDict_Keys(self.Object)
  403. if HasException() {
  404. return nil, GetError()
  405. }
  406. defer C.Py_DecRef(keys)
  407. iterator := C.PyObject_GetIter(keys)
  408. defer C.Py_DecRef(iterator)
  409. dict := make(map[*Reference]*Reference)
  410. for {
  411. key := C.PyIter_Next(iterator);
  412. if key == nil { break }
  413. value := C.PyDict_GetItem(self.Object, key)
  414. if value == nil { continue }
  415. dict[NewReference(key)] = NewReference(value)
  416. }
  417. return dict, nil
  418. }
  419. //
  420. // Set (mutable)
  421. //
  422. var SetType = NewType(&C.PySet_Type)
  423. func NewSet(iterable *Reference) (*Reference, error) {
  424. if set := C.PySet_New(iterable.Object); set != nil {
  425. return NewReference(set), nil
  426. } else {
  427. return nil, GetError()
  428. }
  429. }
  430. func (self *Reference) IsSet() bool {
  431. return self.Type().IsSubtype(SetType)
  432. }
  433. //
  434. // Frozen set (immutable)
  435. //
  436. var FrozenSetType = NewType(&C.PyFrozenSet_Type)
  437. func NewFrozenSet(iterable *Reference) (*Reference, error) {
  438. if frozenSet := C.PyFrozenSet_New(iterable.Object); frozenSet != nil {
  439. return NewReference(frozenSet), nil
  440. } else {
  441. return nil, GetError()
  442. }
  443. }
  444. func (self *Reference) IsFrozenSet() bool {
  445. return self.Type().IsSubtype(FrozenSetType)
  446. }
  447. //
  448. // Bytes (immutable)
  449. //
  450. var BytesType = NewType(&C.PyBytes_Type)
  451. func NewBytes(value []byte) (*Reference, error) {
  452. size := len(value)
  453. value_ := C.CBytes(value)
  454. defer C.free(value_) // TODO: check this!
  455. if bytes := C.PyBytes_FromStringAndSize((*C.char)(value_), C.long(size)); bytes != nil {
  456. return NewReference(bytes), nil
  457. } else {
  458. return nil, GetError()
  459. }
  460. }
  461. func (self *Reference) IsBytes() bool {
  462. // More efficient to use the flag
  463. return self.Type().HasFlag(C.Py_TPFLAGS_BYTES_SUBCLASS)
  464. }
  465. func (self *Reference) ToBytes() ([]byte, error) {
  466. if pointer, size, err := self.AccessBytes(); err == nil {
  467. return C.GoBytes(pointer, C.int(size)), nil
  468. } else {
  469. return nil, err
  470. }
  471. }
  472. func (self *Reference) AccessBytes() (unsafe.Pointer, int, error) {
  473. if string_ := C.PyBytes_AsString(self.Object); string_ != nil {
  474. size := C.PyBytes_Size(self.Object)
  475. return unsafe.Pointer(string_), int(size), nil
  476. } else {
  477. return nil, 0, GetError()
  478. }
  479. }
  480. //
  481. // Byte array (mutable)
  482. //
  483. var ByteArrayType = NewType(&C.PyByteArray_Type)
  484. func NewByteArray(value []byte) (*Reference, error) {
  485. size := len(value)
  486. value_ := C.CBytes(value)
  487. defer C.free(value_) // TODO: check this!
  488. if byteArray := C.PyByteArray_FromStringAndSize((*C.char)(value_), C.long(size)); byteArray != nil {
  489. return NewReference(byteArray), nil
  490. } else {
  491. return nil, GetError()
  492. }
  493. }
  494. func (self *Reference) IsByteArray() bool {
  495. return self.Type().IsSubtype(ByteArrayType)
  496. }
  497. func (self *Reference) ByteArrayToBytes() ([]byte, error) {
  498. if pointer, size, err := self.AccessByteArray(); err == nil {
  499. return C.GoBytes(pointer, C.int(size)), nil
  500. } else {
  501. return nil, err
  502. }
  503. }
  504. func (self *Reference) AccessByteArray() (unsafe.Pointer, int, error) {
  505. if string_ := C.PyByteArray_AsString(self.Object); string_ != nil {
  506. size := C.PyByteArray_Size(self.Object)
  507. return unsafe.Pointer(string_), int(size), nil
  508. } else {
  509. return nil, 0, GetError()
  510. }
  511. }
  512. //
  513. // Object
  514. //
  515. //var ObjectType = NewType(&C.PyObject_Type)
  516. //
  517. //func (self *Reference) IsObject() bool {
  518. // return self.Type().IsSubtype(ObjectType)
  519. //}
  520. func (self *Reference) IsInstance(cls *Reference) (bool, error) {
  521. inst := int64(C.PyObject_IsInstance(self.Object, cls.Object))
  522. if HasException() {
  523. return false, GetError()
  524. }
  525. return inst == 1, nil
  526. }