PageRenderTime 49ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/cpyext/test/test_object.py

https://bitbucket.org/oberstet/pypy
Python | 405 lines | 401 code | 4 blank | 0 comment | 0 complexity | 035a1a7768b39fc6248eb9252bb93740 MD5 | raw file
Possible License(s): Apache-2.0
  1. import py
  2. from pypy.module.cpyext.test.test_api import BaseApiTest
  3. from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
  4. from rpython.rtyper.lltypesystem import rffi, lltype
  5. from pypy.module.cpyext.api import (
  6. Py_LT, Py_LE, Py_NE, Py_EQ, Py_GE, Py_GT)
  7. class TestObject(BaseApiTest):
  8. def test_IsTrue(self, space, api):
  9. assert api.PyObject_IsTrue(space.wrap(1.0)) == 1
  10. assert api.PyObject_IsTrue(space.wrap(False)) == 0
  11. assert api.PyObject_IsTrue(space.wrap(0)) == 0
  12. def test_Not(self, space, api):
  13. assert api.PyObject_Not(space.wrap(False)) == 1
  14. assert api.PyObject_Not(space.wrap(0)) == 1
  15. assert api.PyObject_Not(space.wrap(True)) == 0
  16. assert api.PyObject_Not(space.wrap(3.14)) == 0
  17. def test_exception(self, space, api):
  18. w_obj = space.appexec([], """():
  19. class C:
  20. def __nonzero__(self):
  21. raise ValueError
  22. return C()""")
  23. assert api.PyObject_IsTrue(w_obj) == -1
  24. assert api.PyObject_Not(w_obj) == -1
  25. api.PyErr_Clear()
  26. def test_HasAttr(self, space, api):
  27. hasattr_ = lambda w_obj, name: api.PyObject_HasAttr(w_obj,
  28. space.wrap(name))
  29. assert hasattr_(space.wrap(''), '__len__')
  30. assert hasattr_(space.w_int, '__eq__')
  31. assert not hasattr_(space.w_int, 'nonexistingattr')
  32. buf = rffi.str2charp('__len__')
  33. assert api.PyObject_HasAttrString(space.w_str, buf)
  34. assert not api.PyObject_HasAttrString(space.w_int, buf)
  35. rffi.free_charp(buf)
  36. def test_SetAttr(self, space, api):
  37. w_obj = space.appexec([], """():
  38. class C:
  39. pass
  40. return C()""")
  41. api.PyObject_SetAttr(w_obj, space.wrap('test'), space.wrap(5))
  42. assert not api.PyErr_Occurred()
  43. assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 5
  44. assert api.PyObject_HasAttr(w_obj, space.wrap('test'))
  45. api.PyObject_SetAttr(w_obj, space.wrap('test'), space.wrap(10))
  46. assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 10
  47. buf = rffi.str2charp('test')
  48. api.PyObject_SetAttrString(w_obj, buf, space.wrap(20))
  49. rffi.free_charp(buf)
  50. assert space.unwrap(space.getattr(w_obj, space.wrap('test'))) == 20
  51. def test_getattr(self, space, api):
  52. charp1 = rffi.str2charp("__len__")
  53. charp2 = rffi.str2charp("not_real")
  54. assert api.PyObject_GetAttrString(space.wrap(""), charp1)
  55. assert not api.PyObject_GetAttrString(space.wrap(""), charp2)
  56. assert api.PyErr_Occurred() is space.w_AttributeError
  57. api.PyErr_Clear()
  58. assert api.PyObject_DelAttrString(space.wrap(""), charp1) == -1
  59. assert api.PyErr_Occurred() is space.w_AttributeError
  60. api.PyErr_Clear()
  61. rffi.free_charp(charp1)
  62. rffi.free_charp(charp2)
  63. assert api.PyObject_GetAttr(space.wrap(""), space.wrap("__len__"))
  64. assert api.PyObject_DelAttr(space.wrap(""), space.wrap("__len__")) == -1
  65. api.PyErr_Clear()
  66. def test_getitem(self, space, api):
  67. w_t = space.wrap((1, 2, 3, 4, 5))
  68. assert space.unwrap(api.PyObject_GetItem(w_t, space.wrap(3))) == 4
  69. w_d = space.newdict()
  70. space.setitem(w_d, space.wrap("a key!"), space.wrap(72))
  71. assert space.unwrap(api.PyObject_GetItem(w_d, space.wrap("a key!"))) == 72
  72. assert api.PyObject_SetItem(w_d, space.wrap("key"), space.w_None) == 0
  73. assert space.getitem(w_d, space.wrap("key")) is space.w_None
  74. assert api.PyObject_DelItem(w_d, space.wrap("key")) == 0
  75. assert api.PyObject_GetItem(w_d, space.wrap("key")) is None
  76. assert api.PyErr_Occurred() is space.w_KeyError
  77. api.PyErr_Clear()
  78. def test_size(self, space, api):
  79. assert api.PyObject_Size(space.newlist([space.w_None])) == 1
  80. def test_str(self, space, api):
  81. w_list = space.newlist([space.w_None, space.wrap(42)])
  82. assert space.str_w(api.PyObject_Str(None)) == "<NULL>"
  83. assert space.str_w(api.PyObject_Str(w_list)) == "[None, 42]"
  84. assert space.str_w(api.PyObject_Str(space.wrap("a"))) == "a"
  85. def test_repr(self, space, api):
  86. w_list = space.newlist([space.w_None, space.wrap(42)])
  87. assert space.str_w(api.PyObject_Repr(None)) == "<NULL>"
  88. assert space.str_w(api.PyObject_Repr(w_list)) == "[None, 42]"
  89. assert space.str_w(api.PyObject_Repr(space.wrap("a"))) == "'a'"
  90. def test_RichCompare(self, space, api):
  91. def compare(w_o1, w_o2, opid):
  92. res = api.PyObject_RichCompareBool(w_o1, w_o2, opid)
  93. w_res = api.PyObject_RichCompare(w_o1, w_o2, opid)
  94. assert space.is_true(w_res) == res
  95. return res
  96. def test_compare(o1, o2):
  97. w_o1 = space.wrap(o1)
  98. w_o2 = space.wrap(o2)
  99. for opid, expected in [
  100. (Py_LT, o1 < o2), (Py_LE, o1 <= o2),
  101. (Py_NE, o1 != o2), (Py_EQ, o1 == o2),
  102. (Py_GT, o1 > o2), (Py_GE, o1 >= o2)]:
  103. assert compare(w_o1, w_o2, opid) == expected
  104. test_compare(1, 2)
  105. test_compare(2, 2)
  106. test_compare('2', '1')
  107. w_i = space.wrap(1)
  108. assert api.PyObject_RichCompareBool(w_i, w_i, 123456) == -1
  109. assert api.PyErr_Occurred() is space.w_SystemError
  110. api.PyErr_Clear()
  111. def test_IsInstance(self, space, api):
  112. assert api.PyObject_IsInstance(space.wrap(1), space.w_int) == 1
  113. assert api.PyObject_IsInstance(space.wrap(1), space.w_float) == 0
  114. assert api.PyObject_IsInstance(space.w_True, space.w_int) == 1
  115. assert api.PyObject_IsInstance(
  116. space.wrap(1), space.newtuple([space.w_int, space.w_float])) == 1
  117. assert api.PyObject_IsInstance(space.w_type, space.w_type) == 1
  118. assert api.PyObject_IsInstance(space.wrap(1), space.w_None) == -1
  119. api.PyErr_Clear()
  120. def test_IsSubclass(self, space, api):
  121. assert api.PyObject_IsSubclass(space.w_type, space.w_type) == 1
  122. assert api.PyObject_IsSubclass(space.w_type, space.w_object) == 1
  123. assert api.PyObject_IsSubclass(space.w_object, space.w_type) == 0
  124. assert api.PyObject_IsSubclass(
  125. space.w_type, space.newtuple([space.w_int, space.w_type])) == 1
  126. assert api.PyObject_IsSubclass(space.wrap(1), space.w_type) == -1
  127. api.PyErr_Clear()
  128. def test_fileno(self, space, api):
  129. assert api.PyObject_AsFileDescriptor(space.wrap(1)) == 1
  130. assert api.PyObject_AsFileDescriptor(space.wrap(-20)) == -1
  131. assert api.PyErr_Occurred() is space.w_ValueError
  132. api.PyErr_Clear()
  133. w_File = space.appexec([], """():
  134. class File:
  135. def fileno(self):
  136. return 42
  137. return File""")
  138. w_f = space.call_function(w_File)
  139. assert api.PyObject_AsFileDescriptor(w_f) == 42
  140. def test_hash(self, space, api):
  141. assert api.PyObject_Hash(space.wrap(72)) == 72
  142. assert api.PyObject_Hash(space.wrap(-1)) == -1
  143. assert (api.PyObject_Hash(space.wrap([])) == -1 and
  144. api.PyErr_Occurred() is space.w_TypeError)
  145. api.PyErr_Clear()
  146. def test_type(self, space, api):
  147. assert api.PyObject_Type(space.wrap(72)) is space.w_int
  148. def test_compare(self, space, api):
  149. assert api.PyObject_Compare(space.wrap(42), space.wrap(72)) == -1
  150. assert api.PyObject_Compare(space.wrap(72), space.wrap(42)) == 1
  151. assert api.PyObject_Compare(space.wrap("a"), space.wrap("a")) == 0
  152. def test_cmp(self, space, api):
  153. w = space.wrap
  154. with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
  155. assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
  156. assert ptr[0] == -1
  157. assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
  158. assert ptr[0] == 0
  159. assert api.PyObject_Cmp(w(u"\xe9"), w("\xe9"), ptr) < 0
  160. assert api.PyErr_Occurred()
  161. api.PyErr_Clear()
  162. def test_unicode(self, space, api):
  163. assert space.unwrap(api.PyObject_Unicode(None)) == u"<NULL>"
  164. assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
  165. assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"
  166. assert api.PyObject_Unicode(space.wrap("\xe9")) is None
  167. api.PyErr_Clear()
  168. def test_dir(self, space, api):
  169. w_dir = api.PyObject_Dir(space.sys)
  170. assert space.isinstance_w(w_dir, space.w_list)
  171. assert space.is_true(space.contains(w_dir, space.wrap('modules')))
  172. class AppTestObject(AppTestCpythonExtensionBase):
  173. def setup_class(cls):
  174. AppTestCpythonExtensionBase.setup_class.im_func(cls)
  175. cls.w_tmpname = cls.space.wrap(str(py.test.ensuretemp("out", dir=0)))
  176. def test_TypeCheck(self):
  177. module = self.import_extension('foo', [
  178. ("typecheck", "METH_VARARGS",
  179. """
  180. PyObject *obj = PyTuple_GET_ITEM(args, 0);
  181. PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 1);
  182. return PyBool_FromLong(PyObject_TypeCheck(obj, type));
  183. """)])
  184. assert module.typecheck(1, int)
  185. assert module.typecheck('foo', str)
  186. assert module.typecheck('foo', object)
  187. assert module.typecheck(1L, long)
  188. assert module.typecheck(True, bool)
  189. assert module.typecheck(1.2, float)
  190. assert module.typecheck(int, type)
  191. def test_print(self):
  192. module = self.import_extension('foo', [
  193. ("dump", "METH_VARARGS",
  194. """
  195. PyObject *fname = PyTuple_GetItem(args, 0);
  196. PyObject *obj = PyTuple_GetItem(args, 1);
  197. FILE *fp = fopen(PyString_AsString(fname), "wb");
  198. int ret;
  199. if (fp == NULL)
  200. Py_RETURN_NONE;
  201. ret = PyObject_Print(obj, fp, Py_PRINT_RAW);
  202. fclose(fp);
  203. if (ret < 0)
  204. return NULL;
  205. Py_RETURN_TRUE;
  206. """)])
  207. assert module.dump(self.tmpname, None)
  208. assert open(self.tmpname).read() == 'None'
  209. class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
  210. """
  211. PyBuffer_FillInfo populates the fields of a Py_buffer from its arguments.
  212. """
  213. def test_fillWithoutObject(self):
  214. """
  215. PyBuffer_FillInfo populates the C{buf} and C{length}fields of the
  216. Py_buffer passed to it.
  217. """
  218. module = self.import_extension('foo', [
  219. ("fillinfo", "METH_VARARGS",
  220. """
  221. Py_buffer buf;
  222. PyObject *str = PyString_FromString("hello, world.");
  223. PyObject *result;
  224. if (PyBuffer_FillInfo(&buf, NULL, PyString_AsString(str), 13, 0, 0)) {
  225. return NULL;
  226. }
  227. /* Check a few things we want to have happened.
  228. */
  229. if (buf.buf != PyString_AsString(str)) {
  230. PyErr_SetString(PyExc_ValueError, "buf field not initialized");
  231. return NULL;
  232. }
  233. if (buf.len != 13) {
  234. PyErr_SetString(PyExc_ValueError, "len field not initialized");
  235. return NULL;
  236. }
  237. if (buf.obj != NULL) {
  238. PyErr_SetString(PyExc_ValueError, "obj field not initialized");
  239. return NULL;
  240. }
  241. /* Give back a new string to the caller, constructed from data in the
  242. * Py_buffer.
  243. */
  244. if (!(result = PyString_FromStringAndSize(buf.buf, buf.len))) {
  245. return NULL;
  246. }
  247. /* Free that string we allocated above. result does not share storage with
  248. * it.
  249. */
  250. Py_DECREF(str);
  251. return result;
  252. """)])
  253. result = module.fillinfo()
  254. assert "hello, world." == result
  255. def test_fillWithObject(self):
  256. """
  257. PyBuffer_FillInfo populates the C{buf}, C{length}, and C{obj} fields of
  258. the Py_buffer passed to it and increments the reference count of the
  259. object.
  260. """
  261. module = self.import_extension('foo', [
  262. ("fillinfo", "METH_VARARGS",
  263. """
  264. Py_buffer buf;
  265. PyObject *str = PyString_FromString("hello, world.");
  266. PyObject *result;
  267. if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13, 0, 0)) {
  268. return NULL;
  269. }
  270. /* Get rid of our own reference to the object, but the Py_buffer should
  271. * still have a reference.
  272. */
  273. Py_DECREF(str);
  274. /* Give back a new string to the caller, constructed from data in the
  275. * Py_buffer. It better still be valid.
  276. */
  277. if (!(result = PyString_FromStringAndSize(buf.buf, buf.len))) {
  278. return NULL;
  279. }
  280. /* Now the data in the Py_buffer is really no longer needed, get rid of it
  281. *(could use PyBuffer_Release here, but that would drag in more code than
  282. * necessary).
  283. */
  284. Py_DECREF(buf.obj);
  285. /* Py_DECREF can't directly signal error to us, but if it makes a reference
  286. * count go negative, it will set an error.
  287. */
  288. if (PyErr_Occurred()) {
  289. return NULL;
  290. }
  291. return result;
  292. """)])
  293. result = module.fillinfo()
  294. assert "hello, world." == result
  295. def test_fillReadonly(self):
  296. """
  297. PyBuffer_FillInfo fails if WRITABLE is passed but object is readonly.
  298. """
  299. module = self.import_extension('foo', [
  300. ("fillinfo", "METH_VARARGS",
  301. """
  302. Py_buffer buf;
  303. PyObject *str = PyString_FromString("hello, world.");
  304. PyObject *result;
  305. if (PyBuffer_FillInfo(&buf, str, PyString_AsString(str), 13,
  306. 1, PyBUF_WRITABLE)) {
  307. Py_DECREF(str);
  308. return NULL;
  309. }
  310. Py_DECREF(str);
  311. PyBuffer_Release(&buf);
  312. Py_RETURN_NONE;
  313. """)])
  314. raises(ValueError, module.fillinfo)
  315. class AppTestPyBuffer_Release(AppTestCpythonExtensionBase):
  316. """
  317. PyBuffer_Release releases the resources held by a Py_buffer.
  318. """
  319. def test_decrefObject(self):
  320. """
  321. The PyObject referenced by Py_buffer.obj has its reference count
  322. decremented by PyBuffer_Release.
  323. """
  324. module = self.import_extension('foo', [
  325. ("release", "METH_VARARGS",
  326. """
  327. Py_buffer buf;
  328. buf.obj = PyString_FromString("release me!");
  329. buf.buf = PyString_AsString(buf.obj);
  330. buf.len = PyString_Size(buf.obj);
  331. /* The Py_buffer owns the only reference to that string. Release the
  332. * Py_buffer and the string should be released as well.
  333. */
  334. PyBuffer_Release(&buf);
  335. assert(!buf.obj);
  336. PyBuffer_Release(&buf); /* call again, should not have any more effect */
  337. PyBuffer_Release(&buf);
  338. PyBuffer_Release(&buf);
  339. Py_RETURN_NONE;
  340. """)])
  341. assert module.release() is None