Source

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

Full commit
Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… e7b8954 


Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… e7b8954 
















Armin Rigo 171b149 
Maciej Fijalkows… 6eb46c5 
Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… 6eb46c5 

Maciej Fijalkows… e7b8954 













Maciej Fijalkows… 6eb46c5 
Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… 6eb46c5 

Maciej Fijalkows… e7b8954 











Maciej Fijalkows… 6eb46c5 
Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… 6eb46c5 

Maciej Fijalkows… e7b8954 













Amaury Forgeot d… 3704ca0 


Amaury Forgeot d… ef4fd31 
Maciej Fijalkows… 6eb46c5 

Maciej Fijalkows… e7b8954 












Armin Rigo 613b8b6 














Amaury Forgeot d… 7fd659f 
Armin Rigo 613b8b6 
Maciej Fijalkows… e7b8954 
Amaury Forgeot d… ed5f644 






Maciej Fijalkows… 0e1d57f 



Amaury Forgeot d… 74cb13e 
Maciej Fijalkows… 8bfc71b 
Amaury Forgeot d… 74cb13e 
Maciej Fijalkows… 0e1d57f 
Amaury Forgeot d… cdc5f47 
Maciej Fijalkows… e7b8954 
Amaury Forgeot d… cdc5f47 


Amaury Forgeot d… 74cb13e 
Maciej Fijalkows… e7b8954 




Amaury Forgeot d… 53608a8 
Alex Gaynor a3159d8 

Amaury Forgeot d… 74cb13e 
Alex Gaynor a3159d8 
Amaury Forgeot d… 694c8d7 

Amaury Forgeot d… 74cb13e 
Amaury Forgeot d… 694c8d7 


Amaury Forgeot d… 74cb13e 
Alex Gaynor 9c83472 

Amaury Forgeot d… 74cb13e 
Alex Gaynor 9c83472 
Amaury Forgeot d… 74cb13e 
Alex Gaynor 9c83472 

Maciej Fijalkows… e7b8954 
Amaury Forgeot d… 5a6012e 




Amaury Forgeot d… 6d84b40 
Amaury Forgeot d… 5a6012e 

Amaury Forgeot d… 6d84b40 

Amaury Forgeot d… 778f541 


Amaury Forgeot d… 6d84b40 

Amaury Forgeot d… 53608a8 

Amaury Forgeot d… 6d84b40 
Maciej Fijalkows… e7b8954 
















Amaury Forgeot d… 53608a8 
Maciej Fijalkows… e7b8954 
Alex Gaynor 3871e60 


Amaury Forgeot d… 53608a8 
Alex Gaynor 0e494a0 



Alex Gaynor a06b6f6 
Amaury Forgeot d… 53608a8 
Amaury Forgeot d… 712f089 











Amaury Forgeot d… 48571fe 




Alex Gaynor 0cf4c70 







Alex Gaynor 3871e60 
Amaury Forgeot d… 632ae7b 













Amaury Forgeot d… 4e7b879 




















Amaury Forgeot d… 6216fbf 



Amaury Forgeot d… e6d78e8 
Alex Gaynor 3871e60 
Amaury Forgeot d… 2017ff8 














Maciej Fijalkows… e7b8954 
Amaury Forgeot d… ef4fd31 













Maciej Fijalkows… e7b8954 











Amaury Forgeot d… cfd786c 








Alex Gaynor 3871e60 
Amaury Forgeot d… 46f388d 
Amaury Forgeot d… caaff8a 








Amaury Forgeot d… 774f465 





Amaury Forgeot d… caaff8a 



Amaury Forgeot d… 774f465 
Amaury Forgeot d… caaff8a 
Amaury Forgeot d… 46f388d 
















Amaury Forgeot d… 4c36d55 



















Amaury Forgeot d… d4588ab 
Amaury Forgeot d… 4e7b879 
Amaury Forgeot d… d4588ab 















Armin Rigo 9e1ad87 
















Armin Rigo 7da597d 




Armin Rigo 9e1ad87 








Armin Rigo 7da597d 

Amaury Forgeot d… 873f837 
Armin Rigo 849cc68 



























Amaury Forgeot d… 873f837 



























Amaury Forgeot d… 4e5b2e1 


















































  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
from pypy.module.cpyext.typeobject import PyTypeObjectPtr

import py
import sys

class AppTestTypeObject(AppTestCpythonExtensionBase):
    def test_typeobject(self):
        import sys
        module = self.import_module(name='foo')
        assert 'foo' in sys.modules
        assert "copy" in dir(module.fooType)
        obj = module.new()
        print obj.foo
        assert obj.foo == 42
        print "Obj has type", type(obj)
        assert type(obj) is module.fooType
        print "type of obj has type", type(type(obj))
        print "type of type of obj has type", type(type(type(obj)))
        assert module.fooType.__doc__ == "foo is for testing."

    def test_typeobject_method_descriptor(self):
        module = self.import_module(name='foo')
        obj = module.new()
        obj2 = obj.copy()
        assert module.new().name == "Foo Example"
        c = module.fooType.copy
        assert not "im_func" in dir(module.fooType.copy)
        assert module.fooType.copy.__objclass__ is module.fooType
        assert "copy" in repr(module.fooType.copy)
        assert repr(module.fooType) == "<type 'foo.foo'>"
        assert repr(obj2) == "<Foo>"
        assert repr(module.fooType.__call__) == "<slot wrapper '__call__' of 'foo' objects>"
        assert obj2(foo=1, bar=2) == dict(foo=1, bar=2)

        print obj.foo
        assert obj.foo == 42
        assert obj.int_member == obj.foo

    def test_typeobject_data_member(self):
        module = self.import_module(name='foo')
        obj = module.new()
        obj.int_member = 23
        assert obj.int_member == 23
        obj.int_member = 42
        raises(TypeError, "obj.int_member = 'not a number'")
        raises(TypeError, "del obj.int_member")
        raises(TypeError, "obj.int_member_readonly = 42")
        exc = raises(TypeError, "del obj.int_member_readonly")
        assert "readonly" in str(exc.value)
        raises(SystemError, "obj.broken_member")
        raises(SystemError, "obj.broken_member = 42")
        assert module.fooType.broken_member.__doc__ is None
        assert module.fooType.object_member.__doc__ == "A Python object."

    def test_typeobject_object_member(self):
        module = self.import_module(name='foo')
        obj = module.new()
        assert obj.object_member is None
        obj.object_member = "hello"
        assert obj.object_member == "hello"
        del obj.object_member
        del obj.object_member
        assert obj.object_member is None
        raises(AttributeError, "obj.object_member_ex")
        obj.object_member_ex = None
        assert obj.object_member_ex is None
        obj.object_member_ex = 42
        assert obj.object_member_ex == 42
        del obj.object_member_ex
        raises(AttributeError, "del obj.object_member_ex")

        obj.set_foo = 32
        assert obj.foo == 32

    def test_typeobject_string_member(self):
        module = self.import_module(name='foo')
        obj = module.new()
        assert obj.string_member == "Hello from PyPy"
        raises(TypeError, "obj.string_member = 42")
        raises(TypeError, "del obj.string_member")
        obj.unset_string_member()
        assert obj.string_member is None
        assert obj.string_member_inplace == "spam"
        raises(TypeError, "obj.string_member_inplace = 42")
        raises(TypeError, "del obj.string_member_inplace")
        assert obj.char_member == "s"
        obj.char_member = "a"
        assert obj.char_member == "a"
        raises(TypeError, "obj.char_member = 'spam'")
        raises(TypeError, "obj.char_member = 42")
        #
        import sys
        bignum = sys.maxint - 42
        obj.short_member = -12345;     assert obj.short_member == -12345
        obj.long_member = -bignum;     assert obj.long_member == -bignum
        obj.ushort_member = 45678;     assert obj.ushort_member == 45678
        obj.uint_member = 3000000000;  assert obj.uint_member == 3000000000
        obj.ulong_member = 2*bignum;   assert obj.ulong_member == 2*bignum
        obj.byte_member = -99;         assert obj.byte_member == -99
        obj.ubyte_member = 199;        assert obj.ubyte_member == 199
        obj.bool_member = True;        assert obj.bool_member is True
        obj.float_member = 9.25;       assert obj.float_member == 9.25
        obj.double_member = 9.25;      assert obj.double_member == 9.25
        obj.longlong_member = -2**59;  assert obj.longlong_member == -2**59
        obj.ulonglong_member = 2**63;  assert obj.ulonglong_member == 2**63
        obj.ssizet_member = 2**31;     assert obj.ssizet_member == 2**31
        #

    def test_staticmethod(self):
        module = self.import_module(name="foo")
        obj = module.fooType.create()
        assert obj.foo == 42
        obj2 = obj.create()
        assert obj2.foo == 42

    def test_new(self):
        module = self.import_module(name='foo')
        obj = module.new()
        # call __new__
        newobj = module.UnicodeSubtype(u"xyz")
        assert newobj == u"xyz"
        assert isinstance(newobj, module.UnicodeSubtype)

        assert isinstance(module.fooType(), module.fooType)
        class bar(module.fooType):
            pass
        assert isinstance(bar(), bar)

        fuu = module.UnicodeSubtype
        class fuu2(fuu):
            def baz(self):
                return self
        assert fuu2(u"abc").baz().escape()
        raises(TypeError, module.fooType.object_member.__get__, 1)

    def test_init(self):
        module = self.import_module(name="foo")
        newobj = module.UnicodeSubtype()
        assert newobj.get_val() == 42

        # this subtype should inherit tp_init
        newobj = module.UnicodeSubtype2()
        assert newobj.get_val() == 42

        # this subclass redefines __init__
        class UnicodeSubclass2(module.UnicodeSubtype):
            def __init__(self):
                self.foobar = 32
                super(UnicodeSubclass2, self).__init__()
        
        newobj = UnicodeSubclass2()
        assert newobj.get_val() == 42
        assert newobj.foobar == 32

    def test_metatype(self):
        module = self.import_module(name='foo')
        assert module.MetaType.__mro__ == (module.MetaType, type, object)
        x = module.MetaType('name', (), {})
        assert isinstance(x, type)
        assert isinstance(x, module.MetaType)
        x()

    def test_metaclass_compatible(self):
        # metaclasses should not conflict here
        module = self.import_module(name='foo')
        assert module.MetaType.__mro__ == (module.MetaType, type, object)
        assert type(module.fooType).__mro__ == (type, object)
        y = module.MetaType('other', (module.fooType,), {})
        assert isinstance(y, module.MetaType)
        x = y()
        del x, y

    def test_sre(self):
        module = self.import_module(name='_sre')
        import sre_compile
        sre_compile._sre = module
        assert sre_compile.MAGIC == module.MAGIC
        import re
        import time
        s = u"Foo " * 1000 + u"Bar"
        prog = re.compile(ur"Foo.*Bar")
        assert prog.match(s)
        m = re.search(u"xyz", u"xyzxyz")
        assert m
        m = re.search("xyz", "xyzxyz")
        assert m
        assert "groupdict" in dir(m)
        re._cache.clear()
        re._cache_repl.clear()
        del prog, m

    def test_init_error(self):
        module = self.import_module("foo")
        raises(ValueError, module.InitErrType)

    def test_cmps(self):
        module = self.import_module("comparisons")
        cmpr = module.CmpType()
        assert cmpr == 3
        assert cmpr != 42

    def test_richcompare(self):
        module = self.import_module("comparisons")
        cmpr = module.CmpType()

        # should not crash
        cmpr < 4
        cmpr <= 4
        cmpr > 4
        cmpr >= 4

        assert cmpr.__le__(4) is NotImplemented

    def test_tpcompare(self):
        module = self.import_module("comparisons")
        cmpr = module.OldCmpType()
        assert cmpr < cmpr

    def test_hash(self):
        module = self.import_module("comparisons")
        cmpr = module.CmpType()
        assert hash(cmpr) == 3
        d = {}
        d[cmpr] = 72
        assert d[cmpr] == 72
        assert d[3] == 72

    def test_descriptor(self):
        module = self.import_module("foo")
        prop = module.Property()
        class C(object):
            x = prop
        obj = C()
        assert obj.x == (prop, obj, C)
        assert C.x == (prop, None, C)

        obj.x = 2
        assert obj.y == (prop, 2)
        del obj.x
        assert obj.z == prop

    def test_tp_dict(self):
        foo = self.import_module("foo")
        module = self.import_extension('test', [
           ("read_tp_dict", "METH_O",
            '''
                 PyObject *method;
                 if (!args->ob_type->tp_dict)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 method = PyDict_GetItemString(
                     args->ob_type->tp_dict, "copy");
                 Py_INCREF(method);
                 return method;
             '''
             )
            ])
        obj = foo.new()
        assert module.read_tp_dict(obj) == foo.fooType.copy

    def test_custom_allocation(self):
        foo = self.import_module("foo")
        obj = foo.newCustom()
        assert type(obj) is foo.Custom
        assert type(foo.Custom) is foo.MetaType

    def test_heaptype(self):
        module = self.import_extension('foo', [
           ("name_by_heaptype", "METH_O",
            '''
                 PyHeapTypeObject *heaptype = (PyHeapTypeObject *)args;
                 Py_INCREF(heaptype->ht_name);
                 return heaptype->ht_name;
             '''
             )
            ])
        class C(object):
            pass
        assert module.name_by_heaptype(C) == "C"
        

class TestTypes(BaseApiTest):
    def test_type_attributes(self, space, api):
        w_class = space.appexec([], """():
            class A(object):
                pass
            return A
            """)
        ref = make_ref(space, w_class)

        py_type = rffi.cast(PyTypeObjectPtr, ref)
        assert py_type.c_tp_alloc
        assert from_ref(space, py_type.c_tp_mro).wrappeditems is w_class.mro_w

        api.Py_DecRef(ref)

    def test_multiple_inheritance(self, space, api):
        w_class = space.appexec([], """():
            class A(object):
                pass
            class B(object):
                pass
            class C(A, B):
                pass
            return C
            """)
        ref = make_ref(space, w_class)
        api.Py_DecRef(ref)

    def test_lookup(self, space, api):
        w_type = space.w_str
        w_obj = api._PyType_Lookup(w_type, space.wrap("upper"))
        assert space.is_w(w_obj, space.w_str.getdictvalue(space, "upper"))

        w_obj = api._PyType_Lookup(w_type, space.wrap("__invalid"))
        assert w_obj is None
        assert api.PyErr_Occurred() is None
    
class AppTestSlots(AppTestCpythonExtensionBase):
    def test_some_slots(self):
        module = self.import_extension('foo', [
            ("test_type", "METH_O",
             '''
                 if (!args->ob_type->tp_setattro)
                 {
                     PyErr_SetString(PyExc_ValueError, "missing tp_setattro");
                     return NULL;
                 }
                 if (args->ob_type->tp_setattro ==
                     args->ob_type->tp_base->tp_setattro)
                 {
                     PyErr_SetString(PyExc_ValueError, "recursive tp_setattro");
                     return NULL;
                 }
                 Py_RETURN_TRUE;
             '''
             )
            ])
        assert module.test_type(type(None))

    def test_nb_int(self):
        module = self.import_extension('foo', [
            ("nb_int", "METH_O",
             '''
                 if (!args->ob_type->tp_as_number ||
                     !args->ob_type->tp_as_number->nb_int)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 return args->ob_type->tp_as_number->nb_int(args);
             '''
             )
            ])
        assert module.nb_int(10) == 10
        assert module.nb_int(-12.3) == -12
        raises(ValueError, module.nb_int, "123")

    def test_tp_call(self):
        module = self.import_extension('foo', [
            ("tp_call", "METH_VARARGS",
             '''
                 PyObject *obj = PyTuple_GET_ITEM(args, 0);
                 PyObject *c_args = PyTuple_GET_ITEM(args, 1);
                 if (!obj->ob_type->tp_call)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 return obj->ob_type->tp_call(obj, c_args, NULL);
             '''
             )
            ])
        class C:
            def __call__(self, *args):
                return args
        assert module.tp_call(C(), ('x', 2)) == ('x', 2)

    def test_tp_str(self):
        module = self.import_extension('foo', [
           ("tp_str", "METH_O",
            '''
                 if (!args->ob_type->tp_str)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 return args->ob_type->tp_str(args);
             '''
             )
            ])
        class C:
            def __str__(self):
                return "text"
        assert module.tp_str(C()) == "text"

    def test_mp_ass_subscript(self):
        module = self.import_extension('foo', [
           ("new_obj", "METH_NOARGS",
            '''
                PyObject *obj;
                Foo_Type.tp_as_mapping = &tp_as_mapping;
                tp_as_mapping.mp_ass_subscript = mp_ass_subscript;
                if (PyType_Ready(&Foo_Type) < 0) return NULL;
                obj = PyObject_New(PyObject, &Foo_Type);
                return obj;
            '''
            )],
            '''
            static int
            mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
            {
                if (PyInt_Check(key)) {
                    PyErr_SetNone(PyExc_ZeroDivisionError);
                    return -1;
                }
                return 0;
            }
            PyMappingMethods tp_as_mapping;
            static PyTypeObject Foo_Type = {
                PyVarObject_HEAD_INIT(NULL, 0)
                "foo.foo",
            };
            ''')
        obj = module.new_obj()
        raises(ZeroDivisionError, obj.__setitem__, 5, None)
        res = obj.__setitem__('foo', None)
        assert res is None

    def test_sq_contains(self):
        module = self.import_extension('foo', [
           ("new_obj", "METH_NOARGS",
            '''
                PyObject *obj;
                Foo_Type.tp_as_sequence = &tp_as_sequence;
                tp_as_sequence.sq_contains = sq_contains;
                if (PyType_Ready(&Foo_Type) < 0) return NULL;
                obj = PyObject_New(PyObject, &Foo_Type);
                return obj;
            '''
            )],
            '''
            static int
            sq_contains(PyObject *self, PyObject *value)
            {
                return 42;
            }
            PySequenceMethods tp_as_sequence;
            static PyTypeObject Foo_Type = {
                PyVarObject_HEAD_INIT(NULL, 0)
                "foo.foo",
            };
            ''')
        obj = module.new_obj()
        res = "foo" in obj
        assert res is True

    def test_tp_iter(self):
        module = self.import_extension('foo', [
           ("tp_iter", "METH_O",
            '''
                 if (!args->ob_type->tp_iter)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 return args->ob_type->tp_iter(args);
             '''
             ),
           ("tp_iternext", "METH_O",
            '''
                 if (!args->ob_type->tp_iternext)
                 {
                     PyErr_SetNone(PyExc_ValueError);
                     return NULL;
                 }
                 return args->ob_type->tp_iternext(args);
             '''
             )
            ])
        l = [1]
        it = module.tp_iter(l)
        assert type(it) is type(iter([]))
        assert module.tp_iternext(it) == 1
        raises(StopIteration, module.tp_iternext, it)
        
    def test_bool(self):
        module = self.import_extension('foo', [
            ("newInt", "METH_VARARGS",
             """
                IntLikeObject *intObj;
                long intval;
                PyObject *name;

                if (!PyArg_ParseTuple(args, "i", &intval))
                    return NULL;

                IntLike_Type.tp_as_number = &intlike_as_number;
                intlike_as_number.nb_nonzero = intlike_nb_nonzero;
                if (PyType_Ready(&IntLike_Type) < 0) return NULL;
                intObj = PyObject_New(IntLikeObject, &IntLike_Type);
                if (!intObj) {
                    return NULL;
                }

                intObj->value = intval;
                return (PyObject *)intObj;
             """)],
            """
            typedef struct
            {
                PyObject_HEAD
                int value;
            } IntLikeObject;

            static int
            intlike_nb_nonzero(IntLikeObject *v)
            {
                if (v->value == -42) {
                    PyErr_SetNone(PyExc_ValueError);
                    return -1;
                }
                return v->value;
            }

            PyTypeObject IntLike_Type = {
                PyObject_HEAD_INIT(0)
                /*ob_size*/             0,
                /*tp_name*/             "IntLike",
                /*tp_basicsize*/        sizeof(IntLikeObject),
            };
            static PyNumberMethods intlike_as_number;
            """)
        assert not bool(module.newInt(0))
        assert bool(module.newInt(1))
        assert bool(module.newInt(-1))
        raises(ValueError, bool, module.newInt(-42))