PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/dict.go

http://github.com/qur/gopy
Go | 260 lines | 156 code | 30 blank | 74 comment | 22 complexity | 5e9fac41a0212fc3705fa007330fd1c4 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. // Copyright 2011 Julian Phillips. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package py
  5. // #include "utils.h"
  6. import "C"
  7. import (
  8. "fmt"
  9. "unsafe"
  10. )
  11. // *Dict represents a Python dictionary. In addition to satisfying the Object
  12. // interface, Dict pointers also have a number of methods defined - representing
  13. // the PyDict_XXX functions from the Python C API.
  14. type Dict struct {
  15. AbstractObject
  16. MappingProtocol
  17. o C.PyDictObject
  18. }
  19. // DictType is the Type object that represents the Dict type.
  20. var DictType = (*Type)(unsafe.Pointer(&C.PyDict_Type))
  21. func dictCheck(obj Object) bool {
  22. if obj == nil {
  23. return false
  24. }
  25. return C.dictCheck(c(obj)) != 0
  26. }
  27. func newDict(obj *C.PyObject) *Dict {
  28. return (*Dict)(unsafe.Pointer(obj))
  29. }
  30. // NewDict creates a new empty dictionary.
  31. //
  32. // Return value: New Reference.
  33. func NewDict() (*Dict, error) {
  34. ret := C.PyDict_New()
  35. if ret == nil {
  36. return nil, exception()
  37. }
  38. return newDict(ret), nil
  39. }
  40. func NewDictProxy(obj Object) (*Dict, error) {
  41. ret := C.PyDictProxy_New(c(obj))
  42. if ret == nil {
  43. return nil, exception()
  44. }
  45. return newDict(ret), nil
  46. }
  47. // CheckExact returns true if d is an actual dictionary object, and not an
  48. // instance of a sub type.
  49. func (d *Dict) CheckExact() bool {
  50. ret := C.dictCheckE(c(d))
  51. if int(ret) != 0 {
  52. return true
  53. }
  54. return false
  55. }
  56. // Clear empties the dictionary d of all key-value pairs.
  57. func (d *Dict) Clear() {
  58. C.PyDict_Clear(c(d))
  59. }
  60. // Contains Returns true if the dictionary contains the given key. This is
  61. // equivalent to the Python expression "key in d".
  62. func (d *Dict) Contains(key Object) (bool, error) {
  63. ret := C.PyDict_Contains(c(d), c(key))
  64. return int2BoolErr(ret)
  65. }
  66. // Copy returns a new dictionary that contains the same key-values pairs as d.
  67. //
  68. // Return value: New Reference.
  69. func (d *Dict) Copy() (Object, error) {
  70. ret := C.PyDict_Copy(c(d))
  71. return obj2ObjErr(ret)
  72. }
  73. // SetItem inserts "val" into dictionary d with the key "key". If "key" is not
  74. // hashable, then a TypeError will be returned.
  75. func (d *Dict) SetItem(key, val Object) error {
  76. ret := C.PyDict_SetItem(c(d), c(key), c(val))
  77. return int2Err(ret)
  78. }
  79. // SetItemString inserts "val" into dictionary d with the key "key" (or rather,
  80. // with a *String with the value of "key" will be used as the key). If "key" is
  81. // not hashable, then a TypeError will be returned.
  82. func (d *Dict) SetItemString(key string, val Object) error {
  83. s := C.CString(key)
  84. defer C.free(unsafe.Pointer(s))
  85. ret := C.PyDict_SetItemString(c(d), s, c(val))
  86. return int2Err(ret)
  87. }
  88. // DelItem removes the entry with the key of "key" from the dictionary d. If
  89. // "key" is not hashable, a TypeError is returned.
  90. func (d *Dict) DelItem(key Object) error {
  91. ret := C.PyDict_DelItem(c(d), c(key))
  92. return int2Err(ret)
  93. }
  94. // DelItem removes the entry with the key of "key" (or rather, with a *String
  95. // with the value of "key" as the key) from the dictionary d.
  96. func (d *Dict) DelItemString(key string) error {
  97. s := C.CString(key)
  98. defer C.free(unsafe.Pointer(s))
  99. ret := C.PyDict_DelItemString(c(d), s)
  100. return int2Err(ret)
  101. }
  102. // GetItem returns the Object from dictionary d which has the key "key". If
  103. // there is no such Object, then nil is returned (without an error).
  104. //
  105. // Return value: Borrowed Reference.
  106. func (d *Dict) GetItem(key Object) (Object, error) {
  107. ret := C.PyDict_GetItem(c(d), c(key))
  108. return obj2ObjErr(ret)
  109. }
  110. // GetItemString returns the Object from dictionary d which has the key "key"
  111. // (or rather, which has a *String with the value of "key" as the key). If
  112. // there is no such Object, then nil is returned (without an error).
  113. //
  114. // Return value: Borrowed Reference.
  115. func (d *Dict) GetItemString(key string) (Object, error) {
  116. s := C.CString(key)
  117. defer C.free(unsafe.Pointer(s))
  118. ret := C.PyDict_GetItemString(c(d), s)
  119. return obj2ObjErr(ret)
  120. }
  121. // Items returns a *List containing all the items from the dictionary d, as with
  122. // the Python "d.items()".
  123. //
  124. // Return value: New Reference.
  125. func (d *Dict) Items() (*List, error) {
  126. ret := C.PyDict_Items(c(d))
  127. return newList(ret), exception()
  128. }
  129. // Keys returns a *List containing all the keys from the dictionary d, as with
  130. // the Python "d.keys()".
  131. //
  132. // Return value: New Reference.
  133. func (d *Dict) Keys() (*List, error) {
  134. ret := C.PyDict_Keys(c(d))
  135. return newList(ret), exception()
  136. }
  137. // Values returns a *List containing all the values from the dictionary d, as
  138. // with the Python "d.values()".
  139. //
  140. // Return value: New Reference.
  141. func (d *Dict) Values() (*List, error) {
  142. ret := C.PyDict_Values(c(d))
  143. return newList(ret), exception()
  144. }
  145. // Size returns the number of items in the dictionary d. This is equivalent to
  146. // the Python "len(d)".
  147. func (d *Dict) Size() int64 {
  148. ret := C.PyDict_Size(c(d))
  149. if ret < 0 {
  150. panic(exception())
  151. }
  152. return int64(ret)
  153. }
  154. // PyDict_Next
  155. // Merge merges key values pairs from Object o (which may be a dictionary, or an
  156. // object that supports "o.keys()" and "o[key]") into the dictionary d. If
  157. // override is true then a matching key in d will have it's value replaced by
  158. // the one in o, else the value in d will be left.
  159. func (d *Dict) Merge(o Object, override bool) error {
  160. over := 0
  161. if override {
  162. over = 1
  163. }
  164. ret := C.PyDict_Merge(c(d), c(o), C.int(over))
  165. return int2Err(ret)
  166. }
  167. // Update replaces key values pairs in d with those from o. It is equivalent to
  168. // d.Merge(o, true) in Go, or "d.update(o)" in Python.
  169. func (d *Dict) Update(o Object) error {
  170. ret := C.PyDict_Update(c(d), c(o))
  171. return int2Err(ret)
  172. }
  173. // MergeFromSeq2 merges key values pairs from the Object o (which must be an
  174. // iterable object, where each item is an iterable of length 2 - the key value
  175. // pairs). If override is true then the last key value pair with the same key
  176. // wins, otherwise the first instance does (where an instance already in d
  177. // counts before any in o).
  178. func (d *Dict) MergeFromSeq2(o Object, override bool) error {
  179. over := 0
  180. if override {
  181. over = 1
  182. }
  183. ret := C.PyDict_MergeFromSeq2(c(d), c(o), C.int(over))
  184. return int2Err(ret)
  185. }
  186. // Map returns a Go map that contains the values from the Python dictionary,
  187. // indexed by the keys. The keys and values are the same as in the Python
  188. // dictionary, but changes to the Go map are not propogated back to the Python
  189. // dictionary.
  190. //
  191. // Note: the map holds borrowed references
  192. func (d *Dict) Map() map[Object]Object {
  193. m := make(map[Object]Object, d.Size())
  194. var p C.Py_ssize_t
  195. var k *C.PyObject
  196. var v *C.PyObject
  197. for int(C.PyDict_Next(c(d), &p, &k, &v)) != 0 {
  198. key := newObject(k)
  199. value := newObject(v)
  200. m[key] = value
  201. }
  202. return m
  203. }
  204. // MapString is similar to Map, except that the keys are first converted to
  205. // strings. If the keys are not all Python strings, then an error is returned.
  206. //
  207. // Note: the map holds borrowed references
  208. func (d *Dict) MapString() (map[string]Object, error) {
  209. m := make(map[string]Object, d.Size())
  210. var p C.Py_ssize_t
  211. var k *C.PyObject
  212. var v *C.PyObject
  213. for int(C.PyDict_Next(c(d), &p, &k, &v)) != 0 {
  214. key := newObject(k)
  215. value := newObject(v)
  216. s, ok := key.(*String)
  217. if !ok {
  218. return nil, TypeError.Err("%v is not a string", key)
  219. }
  220. m[s.String()] = value
  221. }
  222. return m, nil
  223. }
  224. // String returns a string representation of the contents of the dictionary d.
  225. func (d *Dict) String() string {
  226. if d == nil {
  227. return "<nil>"
  228. }
  229. return fmt.Sprintf("%v", d.Map())
  230. }