PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/module/cpyext/test/test_tupleobject.py

https://bitbucket.org/pypy/pypy/
Python | 158 lines | 130 code | 14 blank | 14 comment | 4 complexity | 58a9bd71aa61c595261833535735ad86 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from pypy.module.cpyext.pyobject import PyObject, PyObjectP, make_ref, from_ref
  3. from pypy.module.cpyext.tupleobject import PyTupleObject
  4. from pypy.module.cpyext.test.test_api import BaseApiTest
  5. from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
  6. from rpython.rtyper.lltypesystem import rffi, lltype
  7. from rpython.rlib.debug import FatalError
  8. class TestTupleObject(BaseApiTest):
  9. def test_tupleobject(self, space, api):
  10. assert not api.PyTuple_Check(space.w_None)
  11. assert api.PyTuple_SetItem(space.w_None, 0, space.w_None) == -1
  12. atuple = space.newtuple([space.wrap(0), space.wrap(1),
  13. space.wrap('yay')])
  14. assert api.PyTuple_Size(atuple) == 3
  15. #assert api.PyTuple_GET_SIZE(atuple) == 3 --- now a C macro
  16. raises(TypeError, api.PyTuple_Size(space.newlist([])))
  17. api.PyErr_Clear()
  18. def test_tuple_realize_refuses_nulls(self, space, api):
  19. py_tuple = api.PyTuple_New(1)
  20. py.test.raises(FatalError, from_ref, space, py_tuple)
  21. def test_tuple_resize(self, space, api):
  22. w_42 = space.wrap(42)
  23. w_43 = space.wrap(43)
  24. w_44 = space.wrap(44)
  25. ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
  26. py_tuple = api.PyTuple_New(3)
  27. # inside py_tuple is an array of "PyObject *" items which each hold
  28. # a reference
  29. rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42)
  30. rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43)
  31. ar[0] = py_tuple
  32. api._PyTuple_Resize(ar, 2)
  33. w_tuple = from_ref(space, ar[0])
  34. assert space.int_w(space.len(w_tuple)) == 2
  35. assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42
  36. assert space.int_w(space.getitem(w_tuple, space.wrap(1))) == 43
  37. api.Py_DecRef(ar[0])
  38. py_tuple = api.PyTuple_New(3)
  39. rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42)
  40. rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43)
  41. rffi.cast(PyTupleObject, py_tuple).c_ob_item[2] = make_ref(space, w_44)
  42. ar[0] = py_tuple
  43. api._PyTuple_Resize(ar, 10)
  44. assert api.PyTuple_Size(ar[0]) == 10
  45. for i in range(3, 10):
  46. rffi.cast(PyTupleObject, ar[0]).c_ob_item[i] = make_ref(
  47. space, space.wrap(42 + i))
  48. w_tuple = from_ref(space, ar[0])
  49. assert space.int_w(space.len(w_tuple)) == 10
  50. for i in range(10):
  51. assert space.int_w(space.getitem(w_tuple, space.wrap(i))) == 42 + i
  52. api.Py_DecRef(ar[0])
  53. lltype.free(ar, flavor='raw')
  54. def test_setitem(self, space, api):
  55. py_tuple = api.PyTuple_New(2)
  56. api.PyTuple_SetItem(py_tuple, 0, make_ref(space, space.wrap(42)))
  57. api.PyTuple_SetItem(py_tuple, 1, make_ref(space, space.wrap(43)))
  58. w_tuple = from_ref(space, py_tuple)
  59. assert space.eq_w(w_tuple, space.newtuple([space.wrap(42),
  60. space.wrap(43)]))
  61. def test_getslice(self, space, api):
  62. w_tuple = space.newtuple([space.wrap(i) for i in range(10)])
  63. w_slice = api.PyTuple_GetSlice(w_tuple, 3, -3)
  64. assert space.eq_w(w_slice,
  65. space.newtuple([space.wrap(i) for i in range(3, 7)]))
  66. class AppTestTuple(AppTestCpythonExtensionBase):
  67. def test_refcounts(self):
  68. module = self.import_extension('foo', [
  69. ("run", "METH_NOARGS",
  70. """
  71. PyObject *item = PyTuple_New(0);
  72. PyObject *t = PyTuple_New(1);
  73. #ifdef PYPY_VERSION
  74. // PyPy starts even empty tuples with a refcount of 1.
  75. const int initial_item_refcount = 1;
  76. #else
  77. // CPython can cache ().
  78. const int initial_item_refcount = item->ob_refcnt;
  79. #endif // PYPY_VERSION
  80. if (t->ob_refcnt != 1 || item->ob_refcnt != initial_item_refcount) {
  81. PyErr_SetString(PyExc_SystemError, "bad initial refcnt");
  82. return NULL;
  83. }
  84. PyTuple_SetItem(t, 0, item);
  85. if (t->ob_refcnt != 1) {
  86. PyErr_SetString(PyExc_SystemError, "SetItem: t refcnt != 1");
  87. return NULL;
  88. }
  89. if (item->ob_refcnt != initial_item_refcount) {
  90. PyErr_SetString(PyExc_SystemError, "GetItem: item refcnt != initial_item_refcount");
  91. return NULL;
  92. }
  93. if (PyTuple_GetItem(t, 0) != item ||
  94. PyTuple_GetItem(t, 0) != item) {
  95. PyErr_SetString(PyExc_SystemError, "GetItem: bogus item");
  96. return NULL;
  97. }
  98. if (t->ob_refcnt != 1) {
  99. PyErr_SetString(PyExc_SystemError, "GetItem: t refcnt != 1");
  100. return NULL;
  101. }
  102. if (item->ob_refcnt != initial_item_refcount) {
  103. PyErr_SetString(PyExc_SystemError, "GetItem: item refcnt != initial_item_refcount");
  104. return NULL;
  105. }
  106. return t;
  107. """),
  108. ])
  109. x = module.run()
  110. assert x == ((),)
  111. def test_refcounts_more(self):
  112. module = self.import_extension('foo', [
  113. ("run", "METH_NOARGS",
  114. """
  115. long prev;
  116. PyObject *t = PyTuple_New(1);
  117. prev = Py_True->ob_refcnt;
  118. Py_INCREF(Py_True);
  119. PyTuple_SetItem(t, 0, Py_True);
  120. if (Py_True->ob_refcnt != prev + 1) {
  121. PyErr_SetString(PyExc_SystemError,
  122. "SetItem: Py_True refcnt != prev + 1");
  123. return NULL;
  124. }
  125. Py_DECREF(t);
  126. if (Py_True->ob_refcnt != prev) {
  127. PyErr_SetString(PyExc_SystemError,
  128. "after: Py_True refcnt != prev");
  129. return NULL;
  130. }
  131. Py_INCREF(Py_None);
  132. return Py_None;
  133. """),
  134. ])
  135. module.run()
  136. def test_tuple_subclass(self):
  137. module = self.import_module(name='foo')
  138. a = module.TupleLike([1, 2, 3])
  139. assert module.is_TupleLike(a) == 1