PageRenderTime 65ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/module/cpyext/test/test_typeobject.py

https://bitbucket.org/vanl/pypy
Python | 596 lines | 550 code | 30 blank | 16 comment | 3 complexity | 953aeeda00b2ea9637ad1e29f6a7d47c MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, AGPL-3.0
  1. from rpython.rtyper.lltypesystem import rffi, lltype
  2. from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
  3. from pypy.module.cpyext.test.test_api import BaseApiTest
  4. from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
  5. from pypy.module.cpyext.typeobject import PyTypeObjectPtr
  6. import py
  7. import sys
  8. class AppTestTypeObject(AppTestCpythonExtensionBase):
  9. def test_typeobject(self):
  10. import sys
  11. module = self.import_module(name='foo')
  12. assert 'foo' in sys.modules
  13. assert "copy" in dir(module.fooType)
  14. obj = module.new()
  15. print(obj.foo)
  16. assert obj.foo == 42
  17. print("Obj has type", type(obj))
  18. assert type(obj) is module.fooType
  19. print("type of obj has type", type(type(obj)))
  20. print("type of type of obj has type", type(type(type(obj))))
  21. assert module.fooType.__doc__ == "foo is for testing."
  22. def test_typeobject_method_descriptor(self):
  23. module = self.import_module(name='foo')
  24. obj = module.new()
  25. obj2 = obj.copy()
  26. assert module.new().name == "Foo Example"
  27. c = module.fooType.copy
  28. assert not "im_func" in dir(module.fooType.copy)
  29. assert module.fooType.copy.__objclass__ is module.fooType
  30. assert "copy" in repr(module.fooType.copy)
  31. assert repr(module.fooType) == "<type 'foo.foo'>"
  32. assert repr(obj2) == "<Foo>"
  33. assert repr(module.fooType.__call__) == "<slot wrapper '__call__' of 'foo.foo' objects>"
  34. assert obj2(foo=1, bar=2) == dict(foo=1, bar=2)
  35. print(obj.foo)
  36. assert obj.foo == 42
  37. assert obj.int_member == obj.foo
  38. def test_typeobject_data_member(self):
  39. module = self.import_module(name='foo')
  40. obj = module.new()
  41. obj.int_member = 23
  42. assert obj.int_member == 23
  43. obj.int_member = 42
  44. raises(TypeError, "obj.int_member = 'not a number'")
  45. raises(TypeError, "del obj.int_member")
  46. raises(TypeError, "obj.int_member_readonly = 42")
  47. exc = raises(TypeError, "del obj.int_member_readonly")
  48. assert "readonly" in str(exc.value)
  49. raises(SystemError, "obj.broken_member")
  50. raises(SystemError, "obj.broken_member = 42")
  51. assert module.fooType.broken_member.__doc__ is None
  52. assert module.fooType.object_member.__doc__ == "A Python object."
  53. def test_typeobject_object_member(self):
  54. module = self.import_module(name='foo')
  55. obj = module.new()
  56. assert obj.object_member is None
  57. obj.object_member = "hello"
  58. assert obj.object_member == "hello"
  59. del obj.object_member
  60. del obj.object_member
  61. assert obj.object_member is None
  62. raises(AttributeError, "obj.object_member_ex")
  63. obj.object_member_ex = None
  64. assert obj.object_member_ex is None
  65. obj.object_member_ex = 42
  66. assert obj.object_member_ex == 42
  67. del obj.object_member_ex
  68. raises(AttributeError, "del obj.object_member_ex")
  69. obj.set_foo = 32
  70. assert obj.foo == 32
  71. def test_typeobject_string_member(self):
  72. module = self.import_module(name='foo')
  73. obj = module.new()
  74. assert obj.string_member == "Hello from PyPy"
  75. raises(TypeError, "obj.string_member = 42")
  76. raises(TypeError, "del obj.string_member")
  77. obj.unset_string_member()
  78. assert obj.string_member is None
  79. assert obj.string_member_inplace == "spam"
  80. raises(TypeError, "obj.string_member_inplace = 42")
  81. raises(TypeError, "del obj.string_member_inplace")
  82. assert obj.char_member == "s"
  83. obj.char_member = "a"
  84. assert obj.char_member == "a"
  85. raises(TypeError, "obj.char_member = 'spam'")
  86. raises(TypeError, "obj.char_member = 42")
  87. #
  88. import sys
  89. bignum = sys.maxint - 42
  90. obj.short_member = -12345; assert obj.short_member == -12345
  91. obj.long_member = -bignum; assert obj.long_member == -bignum
  92. obj.ushort_member = 45678; assert obj.ushort_member == 45678
  93. obj.uint_member = 3000000000; assert obj.uint_member == 3000000000
  94. obj.ulong_member = 2*bignum; assert obj.ulong_member == 2*bignum
  95. obj.byte_member = -99; assert obj.byte_member == -99
  96. obj.ubyte_member = 199; assert obj.ubyte_member == 199
  97. obj.bool_member = True; assert obj.bool_member is True
  98. obj.float_member = 9.25; assert obj.float_member == 9.25
  99. obj.double_member = 9.25; assert obj.double_member == 9.25
  100. obj.longlong_member = -2**59; assert obj.longlong_member == -2**59
  101. obj.ulonglong_member = 2**63; assert obj.ulonglong_member == 2**63
  102. obj.ssizet_member = sys.maxint;assert obj.ssizet_member == sys.maxint
  103. #
  104. def test_staticmethod(self):
  105. module = self.import_module(name="foo")
  106. obj = module.fooType.create()
  107. assert obj.foo == 42
  108. obj2 = obj.create()
  109. assert obj2.foo == 42
  110. def test_classmethod(self):
  111. module = self.import_module(name="foo")
  112. obj = module.fooType.classmeth()
  113. assert obj is module.fooType
  114. def test_new(self):
  115. module = self.import_module(name='foo')
  116. obj = module.new()
  117. # call __new__
  118. newobj = module.UnicodeSubtype(u"xyz")
  119. assert newobj == u"xyz"
  120. assert isinstance(newobj, module.UnicodeSubtype)
  121. assert isinstance(module.fooType(), module.fooType)
  122. class bar(module.fooType):
  123. pass
  124. assert isinstance(bar(), bar)
  125. fuu = module.UnicodeSubtype
  126. class fuu2(fuu):
  127. def baz(self):
  128. return self
  129. assert fuu2(u"abc").baz().escape()
  130. raises(TypeError, module.fooType.object_member.__get__, 1)
  131. def test_init(self):
  132. module = self.import_module(name="foo")
  133. newobj = module.UnicodeSubtype()
  134. assert newobj.get_val() == 42
  135. # this subtype should inherit tp_init
  136. newobj = module.UnicodeSubtype2()
  137. assert newobj.get_val() == 42
  138. # this subclass redefines __init__
  139. class UnicodeSubclass2(module.UnicodeSubtype):
  140. def __init__(self):
  141. self.foobar = 32
  142. super(UnicodeSubclass2, self).__init__()
  143. newobj = UnicodeSubclass2()
  144. assert newobj.get_val() == 42
  145. assert newobj.foobar == 32
  146. def test_metatype(self):
  147. module = self.import_module(name='foo')
  148. assert module.MetaType.__mro__ == (module.MetaType, type, object)
  149. x = module.MetaType('name', (), {})
  150. assert isinstance(x, type)
  151. assert isinstance(x, module.MetaType)
  152. x()
  153. def test_metaclass_compatible(self):
  154. # metaclasses should not conflict here
  155. module = self.import_module(name='foo')
  156. assert module.MetaType.__mro__ == (module.MetaType, type, object)
  157. assert type(module.fooType).__mro__ == (type, object)
  158. y = module.MetaType('other', (module.fooType,), {})
  159. assert isinstance(y, module.MetaType)
  160. x = y()
  161. del x, y
  162. def test_sre(self):
  163. import sys
  164. for m in ['_sre', 'sre_compile', 'sre_constants', 'sre_parse', 're']:
  165. # clear out these modules
  166. try:
  167. del sys.modules[m]
  168. except KeyError:
  169. pass
  170. module = self.import_module(name='_sre')
  171. import re
  172. assert re.sre_compile._sre is module
  173. s = u"Foo " * 1000 + u"Bar"
  174. prog = re.compile(ur"Foo.*Bar")
  175. assert prog.match(s)
  176. m = re.search(u"xyz", u"xyzxyz")
  177. assert m
  178. m = re.search("xyz", "xyzxyz")
  179. assert m
  180. assert "groupdict" in dir(m)
  181. re._cache.clear()
  182. re._cache_repl.clear()
  183. del prog, m
  184. def test_init_error(self):
  185. module = self.import_module("foo")
  186. raises(ValueError, module.InitErrType)
  187. def test_cmps(self):
  188. module = self.import_module("comparisons")
  189. cmpr = module.CmpType()
  190. assert cmpr == 3
  191. assert cmpr != 42
  192. def test_richcompare(self):
  193. module = self.import_module("comparisons")
  194. cmpr = module.CmpType()
  195. # should not crash
  196. cmpr < 4
  197. cmpr <= 4
  198. cmpr > 4
  199. cmpr >= 4
  200. assert cmpr.__le__(4) is NotImplemented
  201. def test_tpcompare(self):
  202. module = self.import_module("comparisons")
  203. cmpr = module.OldCmpType()
  204. assert cmpr < cmpr
  205. def test_hash(self):
  206. module = self.import_module("comparisons")
  207. cmpr = module.CmpType()
  208. assert hash(cmpr) == 3
  209. d = {}
  210. d[cmpr] = 72
  211. assert d[cmpr] == 72
  212. assert d[3] == 72
  213. def test_descriptor(self):
  214. module = self.import_module("foo")
  215. prop = module.Property()
  216. class C(object):
  217. x = prop
  218. obj = C()
  219. assert obj.x == (prop, obj, C)
  220. assert C.x == (prop, None, C)
  221. obj.x = 2
  222. assert obj.y == (prop, 2)
  223. del obj.x
  224. assert obj.z == prop
  225. def test_tp_dict(self):
  226. foo = self.import_module("foo")
  227. module = self.import_extension('test', [
  228. ("read_tp_dict", "METH_O",
  229. '''
  230. PyObject *method;
  231. if (!args->ob_type->tp_dict)
  232. {
  233. PyErr_SetNone(PyExc_ValueError);
  234. return NULL;
  235. }
  236. method = PyDict_GetItemString(
  237. args->ob_type->tp_dict, "copy");
  238. Py_INCREF(method);
  239. return method;
  240. '''
  241. )
  242. ])
  243. obj = foo.new()
  244. assert module.read_tp_dict(obj) == foo.fooType.copy
  245. def test_custom_allocation(self):
  246. foo = self.import_module("foo")
  247. obj = foo.newCustom()
  248. assert type(obj) is foo.Custom
  249. assert type(foo.Custom) is foo.MetaType
  250. def test_heaptype(self):
  251. module = self.import_extension('foo', [
  252. ("name_by_heaptype", "METH_O",
  253. '''
  254. PyHeapTypeObject *heaptype = (PyHeapTypeObject *)args;
  255. Py_INCREF(heaptype->ht_name);
  256. return heaptype->ht_name;
  257. '''
  258. )
  259. ])
  260. class C(object):
  261. pass
  262. assert module.name_by_heaptype(C) == "C"
  263. def test_type_dict(self):
  264. foo = self.import_module("foo")
  265. module = self.import_extension('test', [
  266. ("hack_tp_dict", "METH_O",
  267. '''
  268. PyTypeObject *type = args->ob_type;
  269. PyObject *a1 = PyLong_FromLong(1);
  270. PyObject *a2 = PyLong_FromLong(2);
  271. PyObject *value;
  272. if (PyDict_SetItemString(type->tp_dict, "a",
  273. a1) < 0)
  274. return NULL;
  275. Py_DECREF(a1);
  276. PyType_Modified(type);
  277. value = PyObject_GetAttrString(type, "a");
  278. Py_DECREF(value);
  279. if (PyDict_SetItemString(type->tp_dict, "a",
  280. a2) < 0)
  281. return NULL;
  282. Py_DECREF(a2);
  283. PyType_Modified(type);
  284. value = PyObject_GetAttrString(type, "a");
  285. return value;
  286. '''
  287. )
  288. ])
  289. obj = foo.new()
  290. assert module.hack_tp_dict(obj) == 2
  291. class TestTypes(BaseApiTest):
  292. def test_type_attributes(self, space, api):
  293. w_class = space.appexec([], """():
  294. class A(object):
  295. pass
  296. return A
  297. """)
  298. ref = make_ref(space, w_class)
  299. py_type = rffi.cast(PyTypeObjectPtr, ref)
  300. assert py_type.c_tp_alloc
  301. assert from_ref(space, py_type.c_tp_mro).wrappeditems is w_class.mro_w
  302. api.Py_DecRef(ref)
  303. def test_multiple_inheritance(self, space, api):
  304. w_class = space.appexec([], """():
  305. class A(object):
  306. pass
  307. class B(object):
  308. pass
  309. class C(A, B):
  310. pass
  311. return C
  312. """)
  313. ref = make_ref(space, w_class)
  314. api.Py_DecRef(ref)
  315. def test_lookup(self, space, api):
  316. w_type = space.w_str
  317. w_obj = api._PyType_Lookup(w_type, space.wrap("upper"))
  318. assert space.is_w(w_obj, space.w_str.getdictvalue(space, "upper"))
  319. w_obj = api._PyType_Lookup(w_type, space.wrap("__invalid"))
  320. assert w_obj is None
  321. assert api.PyErr_Occurred() is None
  322. def test_ndarray_ref(self, space, api):
  323. w_obj = space.appexec([], """():
  324. import _numpypy
  325. return _numpypy.multiarray.dtype('int64').type(2)""")
  326. ref = make_ref(space, w_obj)
  327. api.Py_DecRef(ref)
  328. class AppTestSlots(AppTestCpythonExtensionBase):
  329. def test_some_slots(self):
  330. module = self.import_extension('foo', [
  331. ("test_type", "METH_O",
  332. '''
  333. if (!args->ob_type->tp_setattro)
  334. {
  335. PyErr_SetString(PyExc_ValueError, "missing tp_setattro");
  336. return NULL;
  337. }
  338. if (args->ob_type->tp_setattro ==
  339. args->ob_type->tp_base->tp_setattro)
  340. {
  341. PyErr_SetString(PyExc_ValueError, "recursive tp_setattro");
  342. return NULL;
  343. }
  344. Py_RETURN_TRUE;
  345. '''
  346. )
  347. ])
  348. assert module.test_type(type(None))
  349. def test_nb_int(self):
  350. module = self.import_extension('foo', [
  351. ("nb_int", "METH_O",
  352. '''
  353. if (!args->ob_type->tp_as_number ||
  354. !args->ob_type->tp_as_number->nb_int)
  355. {
  356. PyErr_SetNone(PyExc_ValueError);
  357. return NULL;
  358. }
  359. return args->ob_type->tp_as_number->nb_int(args);
  360. '''
  361. )
  362. ])
  363. assert module.nb_int(10) == 10
  364. assert module.nb_int(-12.3) == -12
  365. raises(ValueError, module.nb_int, "123")
  366. def test_tp_call(self):
  367. module = self.import_extension('foo', [
  368. ("tp_call", "METH_VARARGS",
  369. '''
  370. PyObject *obj = PyTuple_GET_ITEM(args, 0);
  371. PyObject *c_args = PyTuple_GET_ITEM(args, 1);
  372. if (!obj->ob_type->tp_call)
  373. {
  374. PyErr_SetNone(PyExc_ValueError);
  375. return NULL;
  376. }
  377. return obj->ob_type->tp_call(obj, c_args, NULL);
  378. '''
  379. )
  380. ])
  381. class C:
  382. def __call__(self, *args):
  383. return args
  384. assert module.tp_call(C(), ('x', 2)) == ('x', 2)
  385. def test_tp_str(self):
  386. module = self.import_extension('foo', [
  387. ("tp_str", "METH_O",
  388. '''
  389. if (!args->ob_type->tp_str)
  390. {
  391. PyErr_SetNone(PyExc_ValueError);
  392. return NULL;
  393. }
  394. return args->ob_type->tp_str(args);
  395. '''
  396. )
  397. ])
  398. class C:
  399. def __str__(self):
  400. return "text"
  401. assert module.tp_str(C()) == "text"
  402. def test_mp_ass_subscript(self):
  403. module = self.import_extension('foo', [
  404. ("new_obj", "METH_NOARGS",
  405. '''
  406. PyObject *obj;
  407. Foo_Type.tp_as_mapping = &tp_as_mapping;
  408. tp_as_mapping.mp_ass_subscript = mp_ass_subscript;
  409. if (PyType_Ready(&Foo_Type) < 0) return NULL;
  410. obj = PyObject_New(PyObject, &Foo_Type);
  411. return obj;
  412. '''
  413. )],
  414. '''
  415. static int
  416. mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
  417. {
  418. if (PyInt_Check(key)) {
  419. PyErr_SetNone(PyExc_ZeroDivisionError);
  420. return -1;
  421. }
  422. return 0;
  423. }
  424. PyMappingMethods tp_as_mapping;
  425. static PyTypeObject Foo_Type = {
  426. PyVarObject_HEAD_INIT(NULL, 0)
  427. "foo.foo",
  428. };
  429. ''')
  430. obj = module.new_obj()
  431. raises(ZeroDivisionError, obj.__setitem__, 5, None)
  432. res = obj.__setitem__('foo', None)
  433. assert res is None
  434. def test_sq_contains(self):
  435. module = self.import_extension('foo', [
  436. ("new_obj", "METH_NOARGS",
  437. '''
  438. PyObject *obj;
  439. Foo_Type.tp_as_sequence = &tp_as_sequence;
  440. tp_as_sequence.sq_contains = sq_contains;
  441. if (PyType_Ready(&Foo_Type) < 0) return NULL;
  442. obj = PyObject_New(PyObject, &Foo_Type);
  443. return obj;
  444. '''
  445. )],
  446. '''
  447. static int
  448. sq_contains(PyObject *self, PyObject *value)
  449. {
  450. return 42;
  451. }
  452. PySequenceMethods tp_as_sequence;
  453. static PyTypeObject Foo_Type = {
  454. PyVarObject_HEAD_INIT(NULL, 0)
  455. "foo.foo",
  456. };
  457. ''')
  458. obj = module.new_obj()
  459. res = "foo" in obj
  460. assert res is True
  461. def test_tp_iter(self):
  462. module = self.import_extension('foo', [
  463. ("tp_iter", "METH_O",
  464. '''
  465. if (!args->ob_type->tp_iter)
  466. {
  467. PyErr_SetNone(PyExc_ValueError);
  468. return NULL;
  469. }
  470. return args->ob_type->tp_iter(args);
  471. '''
  472. ),
  473. ("tp_iternext", "METH_O",
  474. '''
  475. if (!args->ob_type->tp_iternext)
  476. {
  477. PyErr_SetNone(PyExc_ValueError);
  478. return NULL;
  479. }
  480. return args->ob_type->tp_iternext(args);
  481. '''
  482. )
  483. ])
  484. l = [1]
  485. it = module.tp_iter(l)
  486. assert type(it) is type(iter([]))
  487. assert module.tp_iternext(it) == 1
  488. raises(StopIteration, module.tp_iternext, it)
  489. def test_bool(self):
  490. module = self.import_extension('foo', [
  491. ("newInt", "METH_VARARGS",
  492. """
  493. IntLikeObject *intObj;
  494. long intval;
  495. PyObject *name;
  496. if (!PyArg_ParseTuple(args, "i", &intval))
  497. return NULL;
  498. IntLike_Type.tp_as_number = &intlike_as_number;
  499. intlike_as_number.nb_nonzero = intlike_nb_nonzero;
  500. if (PyType_Ready(&IntLike_Type) < 0) return NULL;
  501. intObj = PyObject_New(IntLikeObject, &IntLike_Type);
  502. if (!intObj) {
  503. return NULL;
  504. }
  505. intObj->value = intval;
  506. return (PyObject *)intObj;
  507. """)],
  508. """
  509. typedef struct
  510. {
  511. PyObject_HEAD
  512. int value;
  513. } IntLikeObject;
  514. static int
  515. intlike_nb_nonzero(IntLikeObject *v)
  516. {
  517. if (v->value == -42) {
  518. PyErr_SetNone(PyExc_ValueError);
  519. return -1;
  520. }
  521. return v->value;
  522. }
  523. PyTypeObject IntLike_Type = {
  524. PyObject_HEAD_INIT(0)
  525. /*ob_size*/ 0,
  526. /*tp_name*/ "IntLike",
  527. /*tp_basicsize*/ sizeof(IntLikeObject),
  528. };
  529. static PyNumberMethods intlike_as_number;
  530. """)
  531. assert not bool(module.newInt(0))
  532. assert bool(module.newInt(1))
  533. assert bool(module.newInt(-1))
  534. raises(ValueError, bool, module.newInt(-42))
  535. def test_tp_new_in_subclass_of_type(self):
  536. skip("BROKEN")
  537. module = self.import_module(name='foo3')
  538. print('calling module.Type()...')
  539. module.Type("X", (object,), {})