PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/bwesterb/pypy
Python | 548 lines | 503 code | 30 blank | 15 comment | 0 complexity | 8b2a34ee04b4c239cf5ee9ac21c94895 MD5 | raw file
  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' 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. module = self.import_module(name='_sre')
  164. import sre_compile
  165. sre_compile._sre = module
  166. assert sre_compile.MAGIC == module.MAGIC
  167. import re
  168. import time
  169. s = u"Foo " * 1000 + u"Bar"
  170. prog = re.compile(ur"Foo.*Bar")
  171. assert prog.match(s)
  172. m = re.search(u"xyz", u"xyzxyz")
  173. assert m
  174. m = re.search("xyz", "xyzxyz")
  175. assert m
  176. assert "groupdict" in dir(m)
  177. re._cache.clear()
  178. re._cache_repl.clear()
  179. del prog, m
  180. def test_init_error(self):
  181. module = self.import_module("foo")
  182. raises(ValueError, module.InitErrType)
  183. def test_cmps(self):
  184. module = self.import_module("comparisons")
  185. cmpr = module.CmpType()
  186. assert cmpr == 3
  187. assert cmpr != 42
  188. def test_richcompare(self):
  189. module = self.import_module("comparisons")
  190. cmpr = module.CmpType()
  191. # should not crash
  192. cmpr < 4
  193. cmpr <= 4
  194. cmpr > 4
  195. cmpr >= 4
  196. assert cmpr.__le__(4) is NotImplemented
  197. def test_tpcompare(self):
  198. module = self.import_module("comparisons")
  199. cmpr = module.OldCmpType()
  200. assert cmpr < cmpr
  201. def test_hash(self):
  202. module = self.import_module("comparisons")
  203. cmpr = module.CmpType()
  204. assert hash(cmpr) == 3
  205. d = {}
  206. d[cmpr] = 72
  207. assert d[cmpr] == 72
  208. assert d[3] == 72
  209. def test_descriptor(self):
  210. module = self.import_module("foo")
  211. prop = module.Property()
  212. class C(object):
  213. x = prop
  214. obj = C()
  215. assert obj.x == (prop, obj, C)
  216. assert C.x == (prop, None, C)
  217. obj.x = 2
  218. assert obj.y == (prop, 2)
  219. del obj.x
  220. assert obj.z == prop
  221. def test_tp_dict(self):
  222. foo = self.import_module("foo")
  223. module = self.import_extension('test', [
  224. ("read_tp_dict", "METH_O",
  225. '''
  226. PyObject *method;
  227. if (!args->ob_type->tp_dict)
  228. {
  229. PyErr_SetNone(PyExc_ValueError);
  230. return NULL;
  231. }
  232. method = PyDict_GetItemString(
  233. args->ob_type->tp_dict, "copy");
  234. Py_INCREF(method);
  235. return method;
  236. '''
  237. )
  238. ])
  239. obj = foo.new()
  240. assert module.read_tp_dict(obj) == foo.fooType.copy
  241. def test_custom_allocation(self):
  242. foo = self.import_module("foo")
  243. obj = foo.newCustom()
  244. assert type(obj) is foo.Custom
  245. assert type(foo.Custom) is foo.MetaType
  246. def test_heaptype(self):
  247. module = self.import_extension('foo', [
  248. ("name_by_heaptype", "METH_O",
  249. '''
  250. PyHeapTypeObject *heaptype = (PyHeapTypeObject *)args;
  251. Py_INCREF(heaptype->ht_name);
  252. return heaptype->ht_name;
  253. '''
  254. )
  255. ])
  256. class C(object):
  257. pass
  258. assert module.name_by_heaptype(C) == "C"
  259. class TestTypes(BaseApiTest):
  260. def test_type_attributes(self, space, api):
  261. w_class = space.appexec([], """():
  262. class A(object):
  263. pass
  264. return A
  265. """)
  266. ref = make_ref(space, w_class)
  267. py_type = rffi.cast(PyTypeObjectPtr, ref)
  268. assert py_type.c_tp_alloc
  269. assert from_ref(space, py_type.c_tp_mro).wrappeditems is w_class.mro_w
  270. api.Py_DecRef(ref)
  271. def test_multiple_inheritance(self, space, api):
  272. w_class = space.appexec([], """():
  273. class A(object):
  274. pass
  275. class B(object):
  276. pass
  277. class C(A, B):
  278. pass
  279. return C
  280. """)
  281. ref = make_ref(space, w_class)
  282. api.Py_DecRef(ref)
  283. def test_lookup(self, space, api):
  284. w_type = space.w_str
  285. w_obj = api._PyType_Lookup(w_type, space.wrap("upper"))
  286. assert space.is_w(w_obj, space.w_str.getdictvalue(space, "upper"))
  287. w_obj = api._PyType_Lookup(w_type, space.wrap("__invalid"))
  288. assert w_obj is None
  289. assert api.PyErr_Occurred() is None
  290. class AppTestSlots(AppTestCpythonExtensionBase):
  291. def test_some_slots(self):
  292. module = self.import_extension('foo', [
  293. ("test_type", "METH_O",
  294. '''
  295. if (!args->ob_type->tp_setattro)
  296. {
  297. PyErr_SetString(PyExc_ValueError, "missing tp_setattro");
  298. return NULL;
  299. }
  300. if (args->ob_type->tp_setattro ==
  301. args->ob_type->tp_base->tp_setattro)
  302. {
  303. PyErr_SetString(PyExc_ValueError, "recursive tp_setattro");
  304. return NULL;
  305. }
  306. Py_RETURN_TRUE;
  307. '''
  308. )
  309. ])
  310. assert module.test_type(type(None))
  311. def test_nb_int(self):
  312. module = self.import_extension('foo', [
  313. ("nb_int", "METH_O",
  314. '''
  315. if (!args->ob_type->tp_as_number ||
  316. !args->ob_type->tp_as_number->nb_int)
  317. {
  318. PyErr_SetNone(PyExc_ValueError);
  319. return NULL;
  320. }
  321. return args->ob_type->tp_as_number->nb_int(args);
  322. '''
  323. )
  324. ])
  325. assert module.nb_int(10) == 10
  326. assert module.nb_int(-12.3) == -12
  327. raises(ValueError, module.nb_int, "123")
  328. def test_tp_call(self):
  329. module = self.import_extension('foo', [
  330. ("tp_call", "METH_VARARGS",
  331. '''
  332. PyObject *obj = PyTuple_GET_ITEM(args, 0);
  333. PyObject *c_args = PyTuple_GET_ITEM(args, 1);
  334. if (!obj->ob_type->tp_call)
  335. {
  336. PyErr_SetNone(PyExc_ValueError);
  337. return NULL;
  338. }
  339. return obj->ob_type->tp_call(obj, c_args, NULL);
  340. '''
  341. )
  342. ])
  343. class C:
  344. def __call__(self, *args):
  345. return args
  346. assert module.tp_call(C(), ('x', 2)) == ('x', 2)
  347. def test_tp_str(self):
  348. module = self.import_extension('foo', [
  349. ("tp_str", "METH_O",
  350. '''
  351. if (!args->ob_type->tp_str)
  352. {
  353. PyErr_SetNone(PyExc_ValueError);
  354. return NULL;
  355. }
  356. return args->ob_type->tp_str(args);
  357. '''
  358. )
  359. ])
  360. class C:
  361. def __str__(self):
  362. return "text"
  363. assert module.tp_str(C()) == "text"
  364. def test_mp_ass_subscript(self):
  365. module = self.import_extension('foo', [
  366. ("new_obj", "METH_NOARGS",
  367. '''
  368. PyObject *obj;
  369. Foo_Type.tp_as_mapping = &tp_as_mapping;
  370. tp_as_mapping.mp_ass_subscript = mp_ass_subscript;
  371. if (PyType_Ready(&Foo_Type) < 0) return NULL;
  372. obj = PyObject_New(PyObject, &Foo_Type);
  373. return obj;
  374. '''
  375. )],
  376. '''
  377. static int
  378. mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
  379. {
  380. if (PyInt_Check(key)) {
  381. PyErr_SetNone(PyExc_ZeroDivisionError);
  382. return -1;
  383. }
  384. return 0;
  385. }
  386. PyMappingMethods tp_as_mapping;
  387. static PyTypeObject Foo_Type = {
  388. PyVarObject_HEAD_INIT(NULL, 0)
  389. "foo.foo",
  390. };
  391. ''')
  392. obj = module.new_obj()
  393. raises(ZeroDivisionError, obj.__setitem__, 5, None)
  394. res = obj.__setitem__('foo', None)
  395. assert res is None
  396. def test_sq_contains(self):
  397. module = self.import_extension('foo', [
  398. ("new_obj", "METH_NOARGS",
  399. '''
  400. PyObject *obj;
  401. Foo_Type.tp_as_sequence = &tp_as_sequence;
  402. tp_as_sequence.sq_contains = sq_contains;
  403. if (PyType_Ready(&Foo_Type) < 0) return NULL;
  404. obj = PyObject_New(PyObject, &Foo_Type);
  405. return obj;
  406. '''
  407. )],
  408. '''
  409. static int
  410. sq_contains(PyObject *self, PyObject *value)
  411. {
  412. return 42;
  413. }
  414. PySequenceMethods tp_as_sequence;
  415. static PyTypeObject Foo_Type = {
  416. PyVarObject_HEAD_INIT(NULL, 0)
  417. "foo.foo",
  418. };
  419. ''')
  420. obj = module.new_obj()
  421. res = "foo" in obj
  422. assert res is True
  423. def test_tp_iter(self):
  424. module = self.import_extension('foo', [
  425. ("tp_iter", "METH_O",
  426. '''
  427. if (!args->ob_type->tp_iter)
  428. {
  429. PyErr_SetNone(PyExc_ValueError);
  430. return NULL;
  431. }
  432. return args->ob_type->tp_iter(args);
  433. '''
  434. ),
  435. ("tp_iternext", "METH_O",
  436. '''
  437. if (!args->ob_type->tp_iternext)
  438. {
  439. PyErr_SetNone(PyExc_ValueError);
  440. return NULL;
  441. }
  442. return args->ob_type->tp_iternext(args);
  443. '''
  444. )
  445. ])
  446. l = [1]
  447. it = module.tp_iter(l)
  448. assert type(it) is type(iter([]))
  449. assert module.tp_iternext(it) == 1
  450. raises(StopIteration, module.tp_iternext, it)
  451. def test_bool(self):
  452. module = self.import_extension('foo', [
  453. ("newInt", "METH_VARARGS",
  454. """
  455. IntLikeObject *intObj;
  456. long intval;
  457. PyObject *name;
  458. if (!PyArg_ParseTuple(args, "i", &intval))
  459. return NULL;
  460. IntLike_Type.tp_as_number = &intlike_as_number;
  461. intlike_as_number.nb_nonzero = intlike_nb_nonzero;
  462. if (PyType_Ready(&IntLike_Type) < 0) return NULL;
  463. intObj = PyObject_New(IntLikeObject, &IntLike_Type);
  464. if (!intObj) {
  465. return NULL;
  466. }
  467. intObj->value = intval;
  468. return (PyObject *)intObj;
  469. """)],
  470. """
  471. typedef struct
  472. {
  473. PyObject_HEAD
  474. int value;
  475. } IntLikeObject;
  476. static int
  477. intlike_nb_nonzero(IntLikeObject *v)
  478. {
  479. if (v->value == -42) {
  480. PyErr_SetNone(PyExc_ValueError);
  481. return -1;
  482. }
  483. return v->value;
  484. }
  485. PyTypeObject IntLike_Type = {
  486. PyObject_HEAD_INIT(0)
  487. /*ob_size*/ 0,
  488. /*tp_name*/ "IntLike",
  489. /*tp_basicsize*/ sizeof(IntLikeObject),
  490. };
  491. static PyNumberMethods intlike_as_number;
  492. """)
  493. assert not bool(module.newInt(0))
  494. assert bool(module.newInt(1))
  495. assert bool(module.newInt(-1))
  496. raises(ValueError, bool, module.newInt(-42))