@@ -980,6 +980,26 @@ def wrapper(*args):
980
980
return wrapper
981
981
982
982
983
+ native_slot_proxy_template = '''
984
+ static PyObject* get_delegate(PyObject* self) {
985
+ return ((ProxyObject*)self)->delegate;
986
+ }
987
+ static void set_delegate(PyObject* self, PyObject* delegate) {
988
+ Py_XSETREF(((ProxyObject*)self)->delegate, delegate);
989
+ }
990
+ static PyObject* proxy_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
991
+ PyObject* delegate;
992
+ if (!PyArg_UnpackTuple(args, "NativeSlotProxy", 0, 1, &delegate))
993
+ return NULL;
994
+ ProxyObject* obj = (ProxyObject*)type->tp_alloc(type, 0);
995
+ if (!obj)
996
+ return NULL;
997
+ obj->delegate = Py_NewRef(delegate); // leaked
998
+ return (PyObject*)obj;
999
+ }
1000
+ '''
1001
+
1002
+
983
1003
def test_nb_slot_calls ():
984
1004
slots = [
985
1005
('proxy_nb_binary_slot' , 'nb_add' ),
@@ -1023,22 +1043,7 @@ def test_nb_slot_calls():
1023
1043
cmembers = 'PyObject* delegate;' ,
1024
1044
code = r'''
1025
1045
typedef NativeNbSlotProxyObject ProxyObject;
1026
- static PyObject* get_delegate(PyObject* self) {
1027
- return ((ProxyObject*)self)->delegate;
1028
- }
1029
- static void set_delegate(PyObject* self, PyObject* delegate) {
1030
- Py_XSETREF(((ProxyObject*)self)->delegate, delegate);
1031
- }
1032
- static PyObject* proxy_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
1033
- PyObject* delegate;
1034
- if (!PyArg_UnpackTuple(args, "NativeNbSlotProxy", 0, 1, &delegate))
1035
- return NULL;
1036
- ProxyObject* obj = (ProxyObject*)type->tp_alloc(type, 0);
1037
- if (!obj)
1038
- return NULL;
1039
- obj->delegate = Py_NewRef(delegate); // leaked
1040
- return (PyObject*)obj;
1041
- }
1046
+ ''' + native_slot_proxy_template + r'''
1042
1047
static PyTypeObject NativeNbSlotProxyType;
1043
1048
#define proxy_nb_unary_slot(slot) \
1044
1049
static PyObject* proxy_##slot(PyObject *a) { \
@@ -1249,22 +1254,7 @@ def test_sq_slot_calls():
1249
1254
cmembers = 'PyObject* delegate;' ,
1250
1255
code = r'''
1251
1256
typedef NativeSqSlotProxyObject ProxyObject;
1252
- static PyObject* get_delegate(PyObject* self) {
1253
- return ((ProxyObject*)self)->delegate;
1254
- }
1255
- static void set_delegate(PyObject* self, PyObject* delegate) {
1256
- Py_XSETREF(((ProxyObject*)self)->delegate, delegate);
1257
- }
1258
- static PyObject* proxy_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
1259
- PyObject* delegate;
1260
- if (!PyArg_UnpackTuple(args, "NativeSqSlotProxy", 0, 1, &delegate))
1261
- return NULL;
1262
- ProxyObject* obj = (ProxyObject*)type->tp_alloc(type, 0);
1263
- if (!obj)
1264
- return NULL;
1265
- obj->delegate = Py_NewRef(delegate); // leaked
1266
- return (PyObject*)obj;
1267
- }
1257
+ ''' + native_slot_proxy_template + r'''
1268
1258
static Py_ssize_t proxy_sq_length(PyObject* self) {
1269
1259
PyObject* delegate = get_delegate(self);
1270
1260
return Py_TYPE(delegate)->tp_as_sequence->sq_length(delegate);
@@ -1388,19 +1378,7 @@ def test_mp_slot_calls():
1388
1378
cmembers = 'PyObject* delegate;' ,
1389
1379
code = r'''
1390
1380
typedef NativeMpSlotProxyObject ProxyObject;
1391
- static PyObject* get_delegate(PyObject* self) {
1392
- return ((ProxyObject*)self)->delegate;
1393
- }
1394
- static PyObject* proxy_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
1395
- PyObject* delegate;
1396
- if (!PyArg_UnpackTuple(args, "NativeMpSlotProxy", 0, 1, &delegate))
1397
- return NULL;
1398
- ProxyObject* obj = (ProxyObject*)type->tp_alloc(type, 0);
1399
- if (!obj)
1400
- return NULL;
1401
- obj->delegate = Py_NewRef(delegate); // leaked
1402
- return (PyObject*)obj;
1403
- }
1381
+ ''' + native_slot_proxy_template + r'''
1404
1382
static Py_ssize_t proxy_mp_length(PyObject* self) {
1405
1383
PyObject* delegate = get_delegate(self);
1406
1384
return Py_TYPE(delegate)->tp_as_mapping->mp_length(delegate);
@@ -1447,25 +1425,13 @@ def __init__(self, delegate):
1447
1425
assert not bool (obj )
1448
1426
1449
1427
1450
- def test_tp_slot_calls ():
1428
+ def test_tp_iter_iternext_calls ():
1451
1429
NativeSlotProxy = CPyExtType (
1452
- name = 'TpSlotProxy ' ,
1430
+ name = 'TpIterSlotProxy ' ,
1453
1431
cmembers = 'PyObject* delegate;' ,
1454
1432
code = r'''
1455
- typedef TpSlotProxyObject ProxyObject;
1456
- static PyObject* get_delegate(PyObject* self) {
1457
- return ((ProxyObject*)self)->delegate;
1458
- }
1459
- static PyObject* proxy_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
1460
- PyObject* delegate;
1461
- if (!PyArg_UnpackTuple(args, "NativeTpSlotProxy", 0, 1, &delegate))
1462
- return NULL;
1463
- ProxyObject* obj = (ProxyObject*)type->tp_alloc(type, 0);
1464
- if (!obj)
1465
- return NULL;
1466
- obj->delegate = Py_NewRef(delegate); // leaked
1467
- return (PyObject*)obj;
1468
- }
1433
+ typedef TpIterSlotProxyObject ProxyObject;
1434
+ ''' + native_slot_proxy_template + r'''
1469
1435
static PyObject* proxy_tp_iter(PyObject* self) {
1470
1436
PyObject* delegate = get_delegate(self);
1471
1437
return Py_TYPE(delegate)->tp_iter(delegate);
@@ -1570,6 +1536,76 @@ def __iter__(self):
1570
1536
assert str (e ).endswith ("is not an iterator" )
1571
1537
1572
1538
1539
+ def test_tp_str_repr_calls ():
1540
+ NativeSlotProxy = CPyExtType (
1541
+ name = 'TpStrSlotProxy' ,
1542
+ cmembers = 'PyObject* delegate;' ,
1543
+ code = r'''
1544
+ typedef TpStrSlotProxyObject ProxyObject;
1545
+ ''' + native_slot_proxy_template + r'''
1546
+ static PyObject* proxy_tp_str(PyObject* self) {
1547
+ PyObject* delegate = get_delegate(self);
1548
+ return Py_TYPE(delegate)->tp_str(delegate);
1549
+ }
1550
+ static PyObject* proxy_tp_repr(PyObject* self) {
1551
+ PyObject* delegate = get_delegate(self);
1552
+ return Py_TYPE(delegate)->tp_repr(delegate);
1553
+ }
1554
+ ''' ,
1555
+ tp_new = 'proxy_tp_new' ,
1556
+ tp_members = '{"delegate", T_OBJECT, offsetof(ProxyObject, delegate), 0, NULL}' ,
1557
+ tp_str = 'proxy_tp_str' ,
1558
+ tp_repr = 'proxy_tp_repr' ,
1559
+ )
1560
+
1561
+ class PureSlotProxy :
1562
+ def __init__ (self , delegate ):
1563
+ self .delegate = delegate
1564
+
1565
+ __str__ = DelegateSlot ()
1566
+ __repr__ = DelegateSlot ()
1567
+
1568
+ for obj in [NativeSlotProxy ("a\n b" ), NativeSlotProxy (PureSlotProxy ("a\n b" ))]:
1569
+ assert str (obj ) == "a\n b"
1570
+ assert repr (obj ) == repr ("a\n b" )
1571
+
1572
+
1573
+ def test_tp_init_calls ():
1574
+ NativeSlotProxy = CPyExtType (
1575
+ name = 'TpInitSlotProxy' ,
1576
+ cmembers = 'PyObject* delegate;' ,
1577
+ code = r'''
1578
+ typedef TpInitSlotProxyObject ProxyObject;
1579
+ ''' + native_slot_proxy_template + r'''
1580
+ int proxy_tp_init(PyObject* self, PyObject* args, PyObject* kwargs) {
1581
+ PyObject* delegate = get_delegate(self);
1582
+ return Py_TYPE(delegate)->tp_init(delegate, args, kwargs);
1583
+ }
1584
+ ''' ,
1585
+ tp_new = 'proxy_tp_new' ,
1586
+ tp_members = '{"delegate", T_OBJECT, offsetof(ProxyObject, delegate), 0, NULL}' ,
1587
+ tp_init = 'proxy_tp_init' ,
1588
+ )
1589
+
1590
+ class PureSlotProxy :
1591
+ def __new__ (cls , delegate ):
1592
+ self = object .__new__ (cls )
1593
+ self .delegate = delegate
1594
+ return self
1595
+
1596
+ def __init__ (self , delegate , * args , ** kwargs ):
1597
+ self .delegate .__init__ (* args , ** kwargs )
1598
+
1599
+ obj = NativeSlotProxy ([1 ])
1600
+ assert obj .delegate == []
1601
+ assert obj .__init__ ({2 }) is None
1602
+ assert obj .delegate == [2 ]
1603
+ assert_raises (TypeError , NativeSlotProxy , ([1 ],), {'a' : 1 })
1604
+
1605
+ obj = NativeSlotProxy (PureSlotProxy ([1 ]))
1606
+ assert obj .delegate .delegate == []
1607
+
1608
+
1573
1609
def test_richcmp ():
1574
1610
MyNativeIntSubType = CPyExtType ("MyNativeIntSubTypeForRichCmpTest" ,
1575
1611
ready_code = "MyNativeIntSubTypeForRichCmpTestType.tp_new = PyLong_Type.tp_new;" ,
@@ -1645,4 +1681,4 @@ def test_cmp(op_lambda, rop_lambda, op_name, rop_name):
1645
1681
1646
1682
assert create_mock (ne = 1 ) == create_mock (eq = 1 )
1647
1683
assert create_mock (ne = 1 , eq = 0 ) != create_mock (ne = 0 , eq = 1 )
1648
- assert not create_mock (ne = 1 , eq = 0 ) == create_mock (ne = 0 , eq = 1 )
1684
+ assert not create_mock (ne = 1 , eq = 0 ) == create_mock (ne = 0 , eq = 1 )
0 commit comments